Discussion:
[Axiom-developer] about Expression Integer
Francois Maltey
2006-02-16 20:33:45 UTC
Permalink
Hello,

Thanks for previous help,
now I can compile a package and add spy-print inside !

I play whith expressions and I have theses questions :

1/ Can I (or cannot) remain Expressions as

x+1/(y+1)
y+1/(x+1)

and do not have a single denominator.

2/ Can I go back from (xy+x+1)/(y+1) to x+1/(y+1) ?
Other cas have normal or partfrac fuction, or remain fraction as.

3/ When I expand a trig formula I cut x+1/(y+1) in x and 1/(y+1)
not in xy/(y+1) and x/(y+1) and 1/(y+1).

But perhaps my ideas aren't right ?

4/ I'm not sure that the results (xy+x+1)/(y+1) and ((x+1)y+1)/(x+1)
are fine :

First the order of the variable is important,
and the user (almost) can't force it, if he uses "n" and "x" variables.

Second the result is longer if the denominator is big.

5/ Of corse there is no problem in expand (cos (4*x+5y)),
but small problems appear with expand (cos (4*x+5*y/2))
and a lot with expand (cos (4*x+5*y/(2+t+t^2+t^3))).

What is the better expand in the 3 cases.
Perhaps cos^4 x ... cos^5 y ...
cos^4 x ... cos^5 (y/2) ...
cos^4 x ... cos^5 (y/(2+t+t^2+t^3)) ... but I'm not sure.


I will be very happy if you can give me your advice, and tell me if
one or an other way of computation is impossible/not natural/too complex
with axiom.

Have a good day.

Francois
Martin Rubey
2006-02-17 08:35:53 UTC
Permalink
Part of this email will become part of MathAction in a minute...
Post by Francois Maltey
1/ Can I (or cannot) remain Expressions as
x+1/(y+1)
y+1/(x+1)
and do not have a single denominator.
Well, I need to explain several things here:

* How can I affect the way Axiom displays its results?

Whenever Axiom needs to write an element of a domain, i.e., an expression from
Expression Integer, a number from PrimeField 5, a factored polynomial from
Factored Polynomial Fraction Integer, etc., to the screen, it calls the
operation with the signature 'coerce: % -> OutputForm' from that domain.

For example, to output a polynomial in factored form, the "real" way to do it
is to coerce it into the domain Factored Polynomial Integer:

Type: Boolean
(6) -> x^2-y^2

2 2
(6) - y + x
Type: Polynomial Integer
(7) -> (x^2-y^2)::Factored Polynomial Integer

(7) - (y - x)(y + x)
Type: Factored Polynomial Integer

Thus, philosophically, the way things are output depends only on the domain,
and if we want to implement a different way, we need to implement a new
domain. This is very easy, see SandBoxDistributedExpression.

* How does this work in Polynomial Integer, Expression Integer?

The domain EXPR INT contains expressions in the form p/q where p and q are
polynomials -- with the variables being the "kernels" -- and the polynomials
are displayed in the same form as in POLY INT, which is unfortunately slightly
confusing. Roughly: "larger" variables are factored out:

(29) -> z*x+x

(29) x z + x
Type: Polynomial Integer
(30) -> z*x+z

(30) (x + 1)z
Type: Polynomial Integer

since "z" is "larger" than "x". Of course, "larger" is simply a rather
arbitrary, but fortunately fixed internal order of the variables. For
Expressions, this order is not even fixed, I think, but I might be wrong here.
In fact, this ordering is the thing about axiom that I hate most, I don't
really want it to say:

(4) -> tan x > sin x

(4) true
Type: Boolean
(5) -> tan x > sin y

(5) true
Type: Boolean

although I got used to it...

* Can I go back from (xy+x+1)/(y+1) to x+1/(y+1) ? Other cas have normal or
partfrac fuction, or remain fraction as.

As follows from the above, this currently cannot be done within the domain EXPR
INT. I think that there are several possibilities, which I will explain on an
old example, the problem of displaying expressions in "fully expanded" form:

* one can write a domain which only overrides the output functionality, and
applies the simplifications every time the element is written on the
screen. That's what I have done for DistributedExpression. This is the quick
and dirty way.

* one writes a new domain with a new representation. For
'DistributedExpression' I failed to do so, since the proper representation
would be 'DMP', but this only accepts a 'List Symbol' as variables, for
expressions I need to allow an arbitrary 'OrderedSet' however.

* one abstracts the form and writes a new functor, as for example
'Factored'. I'm not quite sure, but it may be that a functor 'Distributed'
would be the best solution. I would have to look why the original developers
chose to implement 'DistributedMultivariatePolynomials' instead.

So, the conclusion is that you might want to write a function first that takes
- for example - an expression and returns a list of expressions. It would be
easy to make this into a new domain "MyExpression". I vaguely recall that
Maxima has such a function.
Post by Francois Maltey
3/ When I expand a trig formula I cut x+1/(y+1) in x and 1/(y+1)
not in xy/(y+1) and x/(y+1) and 1/(y+1).
But perhaps my ideas aren't right ?
4/ I'm not sure that the results (xy+x+1)/(y+1) and ((x+1)y+1)/(x+1)
First the order of the variable is important, and the user (almost) can't
force it, if he uses "n" and "x" variables. Second the result is longer if
the denominator is big.
yes, I also think that the way POLY INT works is unsatisfactory. However, there
is DMP, which remedies the situation.
Post by Francois Maltey
5/ Of corse there is no problem in expand (cos (4*x+5y)),
but small problems appear with expand (cos (4*x+5*y/2))
and a lot with expand (cos (4*x+5*y/(2+t+t^2+t^3))).
What is the better expand in the 3 cases.
Perhaps cos^4 x ... cos^5 y ...
cos^4 x ... cos^5 (y/2) ...
cos^4 x ... cos^5 (y/(2+t+t^2+t^3)) ... but I'm not sure.
I believe that usually, it is difficult to decide what's "better". I'd rather
have various operations or domains which all have a clear effect. So, maybe you
just write one operation that fully expands, another one that does something
else, and so on.

The very best thing would be, in my opinion, if you'd devise a domain which
is specially suited for trigonometric functions. I think that devising a really
good expression domain is very complex. Although I must say that I like MuPAD's
very much.

Martin
Bill Page
2006-02-17 23:25:51 UTC
Permalink
Post by Francois Maltey
...
In contrast to most other computer algebra systems, in Axiom
the concept of an 'expression' is not a fundamental idea.
Rather the concept of 'domain' comes first. I think some of
your questions are related to this different point of view.
Post by Francois Maltey
1/ Can I (or cannot) remain Expressions as
x+1/(y+1)
y+1/(x+1)
and do not have a single denominator.
It is possible to do this in several ways. If you do not tell
Axiom anything else, it will interpret your expression as
a member of the domain 'Fraction Polynomial Integer'. That
is why it appears like this:

(1) -> (x+1/(y+1))

x y + x + 1
(1) -----------
y + 1
Type: Fraction Polynomial Integer

This is the first domain that the interpreter finds in which
it can accurately represent your expression, so the expression
is converted to this domain and the result is displayed as you
see above. But notice that your original expression is not a
member of this domain.

There are however more complex domains which do include
expressions of the same form as you wrote above. The interpreter
is not able to find these automatically, but you can help by
specifying more exactly what you want. In the compiler you must
always provide this additional information. For example:

(2) -> (x+1/(y+1))$DMP([x,y],EXPR INT)

1
(2) x + -----
y + 1
Type: DistributedMultivariatePolynomial([x,y],Expression Integer)

(3) -> (y+1/(x+1))$DMP([x,y],EXPR INT)

1
(3) y + -----
x + 1
Type: DistributedMultivariatePolynomial([x,y],Expression Integer)

DMP is the abbreviation for DistributedMultivariatePolynomial. EXPR
is the abbreviation for Expression and of course INT is the abbreviation
for Integer.

In this case your expression is a member of the specified domain and
no conversion is necessary, but notice that the 2nd term is a monomial
of degree 0 since this domain has coefficients that can be expressions.
You might consider this result ambiguous since the entire expression
could be consider a term degree 0, but apparently the domain DMP
attempts construct a polynomial of highest degree? To know for sure
we would probably have to consult the source code for DMP.

I am not sure if this is exactly what you want or what you need as I
will explain below.
Post by Francois Maltey
2/ Can I go back from (xy+x+1)/(y+1) to x+1/(y+1) ?
Other cas have normal or partfrac fuction, or remain fraction as.
Yes. For example:

(4) -> (%%(1)::EXPR INT)::DMP([x,y],EXPR INT)

1
(4) x + -----
y + 1
Type: DistributedMultivariatePolynomial([x,y],Expression Integer)
Post by Francois Maltey
3/ When I expand a trig formula I cut x+1/(y+1) in x and 1/(y+1)
not in xy/(y+1) and x/(y+1) and 1/(y+1).
But perhaps my ideas aren't right ?
I am not sure I understand your use of English. Perhaps you mean
you would like to write:

sin(%%(2))

but unfortunately there is not domain in Axiom right now of which
this expression would be a member. The command ')di op sin' shows
that 'sin' is only defined over domains in the category TRIGCAT.

But this does not mean that you cannot write a function which
performs this expansion. E.g.

(5) -> monomials((%%(1)::EXPR INT)::DMP([x,y],EXPR INT))

1
(5) [x,-----]
y + 1
Type: List DistributedMultivariatePolynomial([x,y],Expression Integer)
Post by Francois Maltey
4/ I'm not sure that the results (xy+x+1)/(y+1) and
First the order of the variable is important, and the user
(almost) can't force it, if he uses "n" and "x" variables.
Second the result is longer if the denominator is big.
Obviously these results are "fine" in the sense that the expressions
belong to the domain 'Fraction Polynomial Integer' which is the
domain that the Axiom interpreter chooses by default. Other results
are possible, as I showed above.
Post by Francois Maltey
5/ Of course there is no problem in expand (cos (4*x+5y)),
but small problems appear with expand (cos (4*x+5*y/2))
and a lot with expand (cos
(4*x+5*y/(2+t+t^2+t^3))).
What is the better expand in the 3 cases.
Perhaps cos^4 x ... cos^5 y ...
cos^4 x ... cos^5 (y/2) ...
cos^4 x ... cos^5 (y/(2+t+t^2+t^3)) ... but I'm not sure.
Yes, I agree with this.
Post by Francois Maltey
I will be very happy if you can give me your advice, and tell
me if one or an other way of computation is impossible/not
natural/too complex with axiom.
I certainly don't think it is too complicated for axiom. To
understand how to use and especially how to program in Axiom
it is necessary to take a quite different view than in most
other computer algebra systems.

Fundamentally, Axiom is "object-oriented". This means that we
must think not about the objects (expressions) themselves but
rather about to what domain they belong. The domain determines
what operations can be performed on it's members. So if you
just write:

x+1/(y+1)

you do not yet have something on which you can operate because
you have not said to which domain it belongs.

One of the important operations defined for almost all domains
is the coercion from that domain to the special domain called
OutputForm. This is the operation that determines how the members
of the domain will appear as output. But keep in mind that how
something appears in output does not directly relate to how it
is represented internally.

Conversions and coercions are very important in Axiom because
they allow you to find equivalent members of other domains that
may include operations of the type that you wish to perform.

To make these operations more "natural" in Axiom it is sometimes
necessary to create new domains. Martin Rubey's reply presents
this idea in more detail.

I hope this is some help.

Regards,
Bill Page.
Martin Rubey
2006-02-18 09:27:42 UTC
Permalink
There are however more complex domains which do include expressions of the
same form as you wrote above. The interpreter is not able to find these
automatically, but you can help by specifying more exactly what you want. In
the compiler you must always provide this additional information. For
(2) -> (x+1/(y+1))$DMP([x,y],EXPR INT)
1
(2) x + -----
y + 1
Type: DistributedMultivariatePolynomial([x,y],Expression Integer)
This is very dangerous!
(3) -> (y+1/(x+1))$DMP([x,y],EXPR INT)
1
(3) y + -----
x + 1
Type: DistributedMultivariatePolynomial([x,y],Expression Integer)
DON'T!
but notice that the 2nd term is a monomial of degree 0 since this domain has
coefficients that can be expressions. You might consider this result
ambiguous since the entire expression could be consider a term degree 0, but
apparently the domain DMP attempts construct a polynomial of highest degree?
This has been thourougly discussed, see

http://wiki.axiom-developer.org/WhereDoVariablesBelong

and the threads mentioned therein.

The main problem you will encounter with the expression above is that you are
really introducing two *different* variables x, so, some time later you may
have Axiom saying x <> x.

The construction above somehow works if you can make sure that your sets of
variables are separated, i.e., when the coefficients contain variables
a,b,c,... and the variables of the polynomial are x,y,z. This is clearly not
the case above.

Martin
Ralf Hemmecke
2006-02-18 19:37:02 UTC
Permalink
Post by Bill Page
Post by Francois Maltey
1/ Can I (or cannot) remain Expressions as
x+1/(y+1)
y+1/(x+1)
and do not have a single denominator.
Unfortunately, I have no idea, how to do this. :-(

But, I'd like to warn you. Don't follow Bill's suggestion.
Post by Bill Page
There are however more complex domains which do include
expressions of the same form as you wrote above. The interpreter
is not able to find these automatically, but you can help by
specifying more exactly what you want. In the compiler you must
(2) -> (x+1/(y+1))$DMP([x,y],EXPR INT)
1
(2) x + -----
y + 1
Type: DistributedMultivariatePolynomial([x,y],Expression Integer)
In this case your expression is a member of the specified domain and
no conversion is necessary, but notice that the 2nd term is a monomial
of degree 0 since this domain has coefficients that can be expressions.
You might consider this result ambiguous since the entire expression
could be consider a term degree 0, but apparently the domain DMP
attempts construct a polynomial of highest degree? To know for sure
we would probably have to consult the source code for DMP.
Right. In order to know what will happen, a user would have to consult
the source code. That's completely unsatisfactory.

Even more, I think the interpreter should forbid to construct things
like DistributedMultivariatePolynomial([x,y],Expression Integer).

Take, for example (axiom--main--1--patch-47)

P := DistributedMultivariatePolynomial([x,y],Expression Integer)
a: P := x
degree a

Are you sure that you expected

[1,0]
Type: DirectProduct(2,NonNegativeInteger)

as output, given the fact that x is an element of the coefficient domain?

Now, it is totally clear that

degree(a/x)

also gives

[1,0]
Type: DirectProduct(2,NonNegativeInteger)

since

a/x

1
(5) - x
x
Type: DistributedMultivariatePolynomial([x,y],Expression Integer)

yields also a completely correct output. ;-) However, I guess, most
people find this confusing.

Ralf
Francois Maltey
2006-02-19 19:01:29 UTC
Permalink
Hello !
Post by Ralf Hemmecke
P := DistributedMultivariatePolynomial([x,y],Expression Integer)
a: P := x
a/x
However, I guess, most people find this confusing.
Indeed...

Why axiom doesn't see the denominator as a DMP ([x,y], Expr Int) ?
The numerator is a DMP ([x,y], Expr Int).

Numerator and denominator of any fraction are in the same ring,
and have the same type.

The x variable can't be a variable of the Expression Integer Ring,
because this a is one of the polynomial.

// 1 //
I was waiting that axiom read a/x as (a::P)/(x::P) because I wait
the same calculus from my students on a sheet of paper.

Is it too difficult ?

// 2 //
I also wait a fail result for the command :
b := monomial(x,[0,0]::DirectProduct(2,NNI))$P

I understand wat is R[X], (R[X])[Y], (R[Y])[X], R[X,Y] and R[Y,X].

I don't understand what is (R[X])[X], so axiom might forget it.

And I don't understand why it's not interessing to add this patch :
.....
However for our purposes something rather primitive is sufficient:
All domains that contain variables need to export a function
variables2: % -> List Symbol. Then we can say in 'QFCAT':

if S has variables2: S -> List Symbol then
variables2: % -> List Symbol
variables2 f ==
merge(variables2(numer(f)), variables2(denom(f)))

and add the following to UP and 'MPOLY':

if R has variables2: R -> List Symbol then
coerce(r:R):% ==
if member?(x, variables2(r)) then
error "coefficient contains variable"
else coerce(r)$Rep
......

// 3 //
Why DMP doesn't accept OrderedSet but only List Symbol ?

* one writes a new domain with a new representation. For
'DistributedExpression' I failed to do so, since the proper representation
would be 'DMP', but this only accepts a 'List Symbol' as variables, for
expressions I need to allow an arbitrary 'OrderedSet' however.

If I'm right Expression are built over POLY which accept OrderedSet
or <<kernel>> as sin x and so.
Ralf Hemmecke
2006-02-18 19:36:35 UTC
Permalink
Post by Bill Page
Conversions and coercions are very important in Axiom because
they allow you to find equivalent members of other domains that
may include operations of the type that you wish to perform.
Is there a big difference between "conversion" and "coercion"?

Ralf
root
2006-02-19 18:22:33 UTC
Permalink
coercions are automatically applied.
conversions are not.

t
Bill Page
2006-02-18 14:06:06 UTC
Permalink
Post by Martin Rubey
Post by Bill Page
There are however more complex domains which do include
expressions of the same form as you wrote above. The
interpreter is not able to find these automatically, but
you can help by specifying more exactly what you want. In
the compiler you must always provide this additional
(2) -> (x+1/(y+1))$DMP([x,y],EXPR INT)
1
(2) x + -----
y + 1
Type: DistributedMultivariatePolynomial([x,y],Expression Integer)
This is very dangerous!
No. I think you are confusing a "bug" with a "feature" here. You can
see this "danger" more clearly in the following simple example:

(1) -> ex1:=(x+1/x)$DMP([x,y],EXPR INT)

1
(1) x + -
x
Type: DistributedMultivariatePolynomial([x,y],Expression Integer)

(2) -> ex2:=ex1*x

2 1
(2) x + - x
x
Type: DistributedMultivariatePolynomial([x,y],Expression Integer)

The second term in (2) is obviously unexpected. The reason is that
Axiom interprets the 'x' in '1/x' that occurs in the coefficient as
a different 'x' than the 'x' that occurs as a variable of the
polynomial. Axiom is continuing to make the distinction between the
use of variables that is allowed in this domain. This is a perfectly
reasonable expression as it stands - it is just not as simple as we
might expect.

But when we ask Axiom to consider this expression as a member of
the 'Expression Integer' domain, we get the simple result that we
probably expected:

(3) -> ex2::EXPR INT

2
(3) x + 1
Type: Expression Integer

So this is not really "dangerous" in the way I think you meant
above.
Post by Martin Rubey
Post by Bill Page
(3) -> (y+1/(x+1))$DMP([x,y],EXPR INT)
1
(3) y + -----
x + 1
Type: DistributedMultivariatePolynomial([x,y],Expression Integer)
DON'T!
Do you mean do not do this in order to avoid unexpected results?
Or do you mean never. If the latter, than I disagree strongly.
Post by Martin Rubey
Post by Bill Page
but notice that the 2nd term is a monomial of degree 0
since this domain has coefficients that can be expressions.
You might consider this result ambiguous since the entire
expression could be consider a term degree 0, but apparently
the domain DMP attempts construct a polynomial of highest
degree?
This has been thoroughly discussed, see
http://wiki.axiom-developer.org/WhereDoVariablesBelong
and the threads mentioned therein.
I have reviewed the discussion again, and I think the conclusions
might be wrong. I am not convinced that this is a bug in the way
Axiom works or design flaw even though the behaviour is radically
different than most other computer algebra systems. In Axiom you
have to be very careful about when and where you test for the
equality of two things.
Post by Martin Rubey
The main problem you will encounter with the expression above
is that you are really introducing two *different* variables
x, so, some time later you may have Axiom saying x <> x.
No that is not true as expression (3) above illustrates.
Post by Martin Rubey
The construction above somehow works if you can make sure
that your sets of variables are separated, i.e., when the
coefficients contain variables a,b,c,... and the variables
of the polynomial are x,y,z. This is clearly not the case
above.
No it is not necessary that the variables be separated, but it
is necessary to remain focused on the domain to which a given
expression belongs. This is one of the features that distinguishes
Axiom from more "primitive" computer algebra systems.

Regards,
Bill Page.
Bill Page
2006-02-19 17:06:05 UTC
Permalink
Post by Ralf Hemmecke
Post by Bill Page
Post by Francois Maltey
1/ Can I (or cannot) remain Expressions as
x+1/(y+1)
y+1/(x+1)
and do not have a single denominator.
Unfortunately, I have no idea, how to do this. :-(
It is obvious, isn't it, that to do this is Axiom you *must*
find a domain of which this expression can be a member?
Post by Ralf Hemmecke
But, I'd like to warn you. Don't follow Bill's suggestion.
I think it is strange how confident both of us are in the
opposite opinion. :)

I don't think you have shown any flaw in my suggestion. It seems
to me to be very reasonable solution to the problem originally
posed by Francois. In fact this same approach is used on other
parts of Axiom.

Perhaps your concern arises because you have not worked out
completely how Axiom uses the concept of domain. I know that
you understand this idea in some depth because of your background
with Aldor. As a programmer and a long term user of Maple, I
had, perhaps, a similar background, but it has taken me more
than two year of working with Axiom to really understand (at
least I think I now understand :) how it is applied to mathematics.
Post by Ralf Hemmecke
Post by Bill Page
There are however more complex domains which do include
expressions of the same form as you wrote above. The interpreter
is not able to find these automatically, but you can help by
specifying more exactly what you want. In the compiler you must
(2) -> (x+1/(y+1))$DMP([x,y],EXPR INT)
1
(2) x + -----
y + 1
Type: DistributedMultivariatePolynomial([x,y],Expression Integer)
In this case your expression is a member of the specified domain
and no conversion is necessary, but notice that the 2nd term is
a monomial of degree 0 since this domain has coefficients that
can be expressions. You might consider this result ambiguous
since the entire expression could be consider a term degree 0,
but apparently the domain DMP attempts construct a polynomial of
highest degree? To know for sure we would probably have to consult
the source code for DMP.
Right. In order to know what will happen, a user would have to
consult the source code. That's completely unsatisfactory.
The solution is *not* to abandon something that is central to
the design of Axiom but rather to write proper, correct and
complete documentation. In particular it is important to realize
that the object that is called a DMP in Axiom is almost, but
not quite that same thing as what a mathematician would call a
polynomial. It is actually something a little more general. It
makes a explicit distinction between the underlying coefficient
domain and the polynomial domain itself. This is something that
one would not (normally) do in mathematics.

There is no problem with this when you think in terms of
programming, but it does sometimes cause some cognitive
dissonance when thinking in terms of the mathematics. In fact
this is quite normal when using other computer algebra systems
as well as Axiom and I think Axiom represents a better
compromise between programming and mathematics than most.
Post by Ralf Hemmecke
Even more, I think the interpreter should forbid to construct
things like DistributedMultivariatePolynomial([x,y],
Expression Integer).
No! I think this would be very much against the overall design
of Axiom. We must be able to construct domains in this manner.
That is where a great deal of power lies in Axiom that is not
available in other computer algebra systems.
Post by Ralf Hemmecke
Take, for example (axiom--main--1--patch-47)
P := DistributedMultivariatePolynomial([x,y],Expression Integer)
a: P := x
degree a
Are you sure that you expected
[1,0]
Type: DirectProduct(2,NonNegativeInteger)
as output, given the fact that x is an element of the coefficient
domain?
Yes. This makes perfectly good sense to me. 'x' is also a polynomial
variable. Since DMP is the highest level domain constructor, I would
expect it to interpret 'x' as being in the polynomial domain first
and only if forced treat is as being in the underlying coefficient
domain.

What about? (Notice that Axiom makes you work harder to say something
like this.)

b := monomial(x,[0,0]::DirectProduct(2,NNI))$P

Can you explain this result?

(23) -> degree b

(23) [0,0]
Type: DirectProduct(2,NonNegativeInteger)

(24) -> b+x

(24) x + x
Type: DistributedMultivariatePolynomial([x,y],Expression Integer)
Post by Ralf Hemmecke
Now, it is totally clear that
degree(a/x)
also gives
[1,0]
Type: DirectProduct(2,NonNegativeInteger)
since
a/x
1
(5) - x
x
Type: DistributedMultivariatePolynomial([x,y],Expression Integer)
yields also a completely correct output. ;-) However, I guess, most
people find this confusing.
I think this is only confusing if you try to think of this
expression out of context, that is, without thinking about the
structure of the domain to which is belongs. Everything that
Axiom is doing here is well-defined and can be useful in the right
context (such as the expansion of trigonometric functions in
Francois' original problem).

It seems to me that Axiom's documentation is deficient because it
does not sufficiently emphasis in what way Axiom differs from other
computer algebra systems. And it does not say nearly enough about
how the fundamental ideas in Axiom such as 'domain' related to the
mathematics that it intends to represent. But I think this is
understandable because what Axiom does in some ways is quite
radical. To really appreciate it takes some time and a lot of work.

The developers of Axiom where quite well aware of this, I think.
That is the reason for the proposal for B# (B natural). Axiom's
current interpreter exposes to much of these details to the first
time user. They need a more gentle introduction to these ideas.
But eventually in order to program in Axiom, it is essential that
they gain a full appreciation of the object-oriented design
philosophy.

Regards,
Bill Page.
Martin Rubey
2006-02-19 18:40:42 UTC
Permalink
Since DMP is the highest level domain constructor, I would expect it to
interpret 'x' as being in the polynomial domain first and only if forced
treat is as being in the underlying coefficient domain.
I believe that this is not always the case, although I don't have an example at
hand.

However, I would like to restate what William Sit and I were able to agree
upon, when we discussed these matters:

Axiom is able to deal (more or less) properly with variables bearing the same
name but having different meanings.

We did not agree on whether we should allow this to happen or not...
b := monomial(x,[0,0]::DirectProduct(2,NNI))$P
Can you explain this result?
(23) -> degree b
(23) [0,0]
Type: DirectProduct(2,NonNegativeInteger)
(24) -> b+x
(24) x + x
Type: DistributedMultivariatePolynomial([x,y],Expression Integer)
Here, we have two *different* "variables", the only happen to bear the same
name.

What I consider very problematic is, that

(b+x)::EXPR INT

gives 2x. I believe that this can lead to very "surprising" results.

In any case, I think it is better not to use such types. Currently, this is not
always possible, it would be necessary to introduce a parametrized Expression
domain, that takes variables as parameters -- this is on the WishList, by the
way. I don't think it would be too much work.

Martin
Ralf Hemmecke
2006-02-20 11:28:42 UTC
Permalink
Post by Bill Page
Post by Ralf Hemmecke
Post by Francois Maltey
1/ Can I (or cannot) remain Expressions as
x+1/(y+1)
y+1/(x+1)
and do not have a single denominator.
Unfortunately, I have no idea, how to do this. :-(
It is obvious, isn't it, that to do this is Axiom you *must*
find a domain of which this expression can be a member?
Of course, you are right. I was just saying that I don't know of a
domain which behaves as one would expect. So the next thing I would do
is to write another domain which behaves (and inherits) most things from
Expression Integer but does not group expressions together so that they
are over one denominator.

Maybe one very simple idea would be to write a domain constructor

ExpressionSum(R:OrderedSet): Exports == Implementation where
Exports ==> -- Same as for Expression(R)
Implementation ==> List Expression R
Rep := List Expression R
(x: %) + (y: %): % == per append(rep x, rep y) -- concat lists
-- The other functions have to be implemented accordingly.
-- That will be a lot of work.
coerce(x: %): OutputForm == map(+, [e::OutputForm for e in rep x])
-- Maybe some parens should be added if the expression has
-- a minus sign

I am not sure, however, whether this is the best idea. Unfortunately, I
don't know all the domains of Axiom so well. So maybe my sugestion is
completely irrelevant since something like that is already existing in
Axiom.
Post by Bill Page
Post by Ralf Hemmecke
But, I'd like to warn you. Don't follow Bill's suggestion.
I think it is strange how confident both of us are in the
opposite opinion. :)
I don't think you have shown any flaw in my suggestion. It seems
to me to be very reasonable solution to the problem originally
posed by Francois. In fact this same approach is used on other
parts of Axiom.
Your suggestion does not work if you want to do the following:

x+1/(y+1) + y+1/(x+1)

since

(x+1/(y+1) + y+1/(x+1))$DMP([x,y],EXPR INT)

shows as

y + x + 2
(4) x + y + ----------------
(x + 1)y + x + 1
Type: DistributedMultivariatePolynomial([x,y],Expression Integer)

Of course, ad hoc solutions are not bad as long as one knows what one is
doing, but I somehow don't like the ad hoc method. Either there is a
clever program that guesses correctly what the user wants, or, if this
is not possible, the user should think a bit more and perhaps add more
knowledge to the system. Otherwise Axiom ends up in being like all the
other untyped CAS.
Post by Bill Page
Perhaps your concern arises because you have not worked out
completely how Axiom uses the concept of domain. I know that
you understand this idea in some depth because of your background
with Aldor. As a programmer and a long term user of Maple, I
had, perhaps, a similar background, but it has taken me more
than two year of working with Axiom to really understand (at
least I think I now understand :) how it is applied to mathematics.
Well, I agree, that you are probably better in applying Axiom to real
world problems, but I hope you agree that if Axiom is not able to do the
things that Francois wants in a clear way, then it would be better (at
least for the future) to add a nice feature to the system instead of
being satisfied that the wish can be fulfilled by an ad-hoc-misuse of
existing domains.
Post by Bill Page
In particular it is important to realize
that the object that is called a DMP in Axiom is almost, but
not quite that same thing as what a mathematician would call a
polynomial. It is actually something a little more general. It
makes a explicit distinction between the underlying coefficient
domain and the polynomial domain itself. This is something that
one would not (normally) do in mathematics.
Well, a polynomial in n variables with coefficients in a ring R is an
element of

\Oplus_{e \in N^n} R

where N is the non-negative integers.

If you like, you can attach variable names somewhere. Yes, I also know
that some people define polynomials differently.

And by the way, 1 is a perfect member of DMP([x,y],Integer) also in
Axiom. I know you know that.

(1) -> a: DMP([x,y],Integer) := 1

(1) 1
Type: DistributedMultivariatePolynomial([x,y],Integer)
Post by Bill Page
What about? (Notice that Axiom makes you work harder to say something
like this.)
b := monomial(x,[0,0]::DirectProduct(2,NNI))$P
Can you explain this result?
(23) -> degree b
(23) [0,0]
Type: DirectProduct(2,NonNegativeInteger)
(24) -> b+x
(24) x + x
Type: DistributedMultivariatePolynomial([x,y],Expression Integer)
So, let me interpret a polynomial as above as a function (with finite
support) from the domain of exponents to the domain of coefficients.

(24) clearly has support { [1,0], [0,0] } an is therefore by no means
equal to the polynomial 2x which has support { [1,0] }.

I am not really saying that Axiom is doing something wrong, I am just
warning that the use of DMP([x,y], Expression Integer) can be misleading
for people that don't know how Axiom works internally. Those people
would probably treat (24) as 2x and that interpretation would be wrong.
Post by Bill Page
Post by Ralf Hemmecke
Now, it is totally clear that
degree(a/x)
also gives
[1,0]
Type: DirectProduct(2,NonNegativeInteger)
since
a/x
1
(5) - x
x
Type: DistributedMultivariatePolynomial([x,y],Expression Integer)
yields also a completely correct output. ;-) However, I guess, most
people find this confusing.
I think this is only confusing if you try to think of this
expression out of context, that is, without thinking about the
structure of the domain to which is belongs.
The context is clearly given. It's the type of (5). Right, I could even
predict, that Axiom should give back that expression. (How could I
otherwise have constructed it?) But the two x's one sees, have different
origins and are therefore not equal.

By the way, you can achieve similar confusing things with Maple.

f:=proc() local x; x end;
a:=f(): b:=f():
evalb(a=b);

That behaviour had once cost me several days to trace down a bug.
Clearly, a looks like x and b looks like x. But they are not equal. I
haven't found this to be documented.
Post by Bill Page
But eventually in order to program in Axiom, it is essential that
they gain a full appreciation of the object-oriented design
philosophy.
I would not really like to call Axiom (or Aldor) object-oriented.
We don't write

a.add(b)

in order to add two numbers.

the function "add" is not attached to the object a. It is rather that a
and b are on equal footing.

Try to program a simple thing as a n-ary polynomial ring in a purely
object-oriented programming language (like for example JAVA even with
generics), then it becomes clear that Axiom has more to offer that the
current trend in programming.

Ralf
Gabriel Dos Reis
2006-02-20 17:15:39 UTC
Permalink
Ralf Hemmecke <***@hemmecke.de> writes:

[...]

| > But eventually in order to program in Axiom, it is essential that
| > they gain a full appreciation of the object-oriented design
| > philosophy.
|
| I would not really like to call Axiom (or Aldor) object-oriented.
| We don't write
|
| a.add(b)
|
| in order to add two numbers.

There is more to object-orientation than "dot notation". To my eyes
and mind, Aldor and Axiom are object-oriented, and they haven't yet
escaped that land :-(

| the function "add" is not attached to the object a. It is rather that
| a and b are on equal footing.

"equal footing" is not contradictory to object orientation.

| Try to program a simple thing as a n-ary polynomial ring in a purely
| object-oriented programming language (like for example JAVA even with
| generics),

Why Java instead of CLOS?

| then it becomes clear that Axiom has more to offer that the
| current trend in programming.

The current trend in programming is some heavy or displcaed emphasis
on generic programming.

-- Gaby
Ralf Hemmecke
2006-02-20 17:57:09 UTC
Permalink
Hallo Gaby,
Post by Gabriel Dos Reis
[...]
| > But eventually in order to program in Axiom, it is essential that
| > they gain a full appreciation of the object-oriented design
| > philosophy.
|
| I would not really like to call Axiom (or Aldor) object-oriented.
| We don't write
|
| a.add(b)
|
| in order to add two numbers.
There is more to object-orientation than "dot notation". To my eyes
and mind, Aldor and Axiom are object-oriented, and they haven't yet
escaped that land :-(
Hmm, do you call the following object-oriented?

(That code appears in libalgebra distributed with Aldor and it basically
provides a generic function that given a function "f: R -> S" returns a
function "map(f)" of type "RX -> SX" that applies "f" on the
coefficients of a univariate polynomial.)

UnivariateFreeRing2(
R : Join(ArithmeticType, ExpressionType),
RX: UnivariateFreeRing R,
S : Join(ArithmeticType, ExpressionType),
SX: UnivariateFreeRing S
): with {
map: (R -> S) -> RX -> SX;
} == add {
map(f:R -> S)(p:RX):SX == {
q:SX := 0;
for term in p repeat {
(c, n) := term;
q := add!(q, f c, n);
}
q;
}
}

What is the class and what are the methods?

Can you write that in JAVA or CLOS? I would be happy to see it.
Post by Gabriel Dos Reis
| the function "add" is not attached to the object a. It is rather that
| a and b are on equal footing.
"equal footing" is not contradictory to object orientation.
Well, you may be right. But when I read about implementation of complex
numbers in C++ and saw that a.add(b) construct, I really did not like it
(at least not in the context of mathematics). It is saying: sent the
message "add" with parameter "b" to the object "a". And it means that
"a" has to do the work since "a" knows how to add something to itself.
It is like saying. The integer 1 knows how another integer can be added
to it. I don't consider that thinking to be quite natural in the context
of mathematics. I agree, object-orientation be appropriate for other
contexts.
Post by Gabriel Dos Reis
| then it becomes clear that Axiom has more to offer that the
| current trend in programming.
The current trend in programming is some heavy or displcaed emphasis
on generic programming.
Sorry that I don't know CLOS, but I have looked a bit into JAVA's
generics. And that is a lot weaker than what was already available in
Aldor several years ago.

BTW, I don't say that Aldor hasn't some kind of object-orientation, but
it is in my opinion not a pure object-oriented language.

Ralf
Gabriel Dos Reis
2006-02-20 21:02:01 UTC
Permalink
Ralf Hemmecke <***@hemmecke.de> writes:

| Hallo Gaby,
|
| On 02/20/2006 06:15 PM, Gabriel Dos Reis wrote:
| > Ralf Hemmecke <***@hemmecke.de> writes:
| > [...]
| > | > But eventually in order to program in Axiom, it is essential that
| > | > they gain a full appreciation of the object-oriented design
| > | > philosophy.
| > | | I would not really like to call Axiom (or Aldor) object-oriented.
| > | We don't write
| > | | a.add(b)
| > | | in order to add two numbers.
| > There is more to object-orientation than "dot notation". To my eyes
| > and mind, Aldor and Axiom are object-oriented, and they haven't yet
| > escaped that land :-(
|
| Hmm, do you call the following object-oriented?

Yes.

| (That code appears in libalgebra distributed with Aldor and it
| basically provides a generic function that given a function "f: R ->
| S" returns a function "map(f)" of type "RX -> SX" that applies "f" on
| the coefficients of a univariate polynomial.)
|
| UnivariateFreeRing2(
| R : Join(ArithmeticType, ExpressionType),
| RX: UnivariateFreeRing R,
| S : Join(ArithmeticType, ExpressionType),
| SX: UnivariateFreeRing S
| ): with {
| map: (R -> S) -> RX -> SX;
| } == add {
| map(f:R -> S)(p:RX):SX == {
| q:SX := 0;
| for term in p repeat {
| (c, n) := term;
| q := add!(q, f c, n);
| }
| q;
| }
| }
|
| What is the class and what are the methods?

The class is the collection of "things" that you can "pretend" to be
univariate polynomials.
The methods are the necessary supporting functions you need to collect the
coefficients into something you "pretend" is a univariate polynomial.
For example here, add! is one of those methods.

| Can you write that in JAVA or CLOS? I would be happy to see it.
|
| > | the function "add" is not attached to the object a. It is rather that
| > | a and b are on equal footing.
| > "equal footing" is not contradictory to object orientation.
|
| Well, you may be right. But when I read about implementation of
| complex numbers in C++ and saw that a.add(b) construct, I really did
| not like it (at least not in the context of mathematics).

The (standard) complex number implementations of C++ I know of do not
have "a.add(b)", and surely the implementations I'm familiar with do
not claim "object orientation", quite the contrary.

| It is
| saying: sent the message "add" with parameter "b" to the object
| "a". And it means that "a" has to do the work since "a" knows how to
| add something to itself.

In the C++ implementations I'm familiar with, it is written "a + b".

| It is like saying. The integer 1 knows how another integer can be
| added to it. I don't consider that thinking to be quite natural in the
| context of mathematics. I agree, object-orientation be appropriate for
| other contexts.
|
| > | then it becomes clear that Axiom has more to offer that the
| > | current trend in programming.
|
| > The current trend in programming is some heavy or displcaed emphasis
| > on generic programming.
|
| Sorry that I don't know CLOS,

The reason why I mention CLOS is that it is close to Lisp (given the
general topic of this mailing list :-), it has an object system, and
given the _topic_,it has *multi-methods* (though I don't particularly
like their ambiguity resolution.)

| but I have looked a bit into JAVA's
| generics. And that is a lot weaker than what was already available in
| Aldor several years ago.

I believe you. But again, I'm skeptical that we are going to make
Axiom lead if we insist on comparing with Java. More advanced systems
are around (e.g. Haskell).

| BTW, I don't say that Aldor hasn't some kind of object-orientation,
| but it is in my opinion not a pure object-oriented language.

My view is that debates of "pure" <your-favorite-buzzword> are
meaningless as far as productive system building is concerned.
So, I will stop here.

-- Gaby
Ralf Hemmecke
2006-02-21 11:05:11 UTC
Permalink
Post by Gabriel Dos Reis
| Hmm, do you call the following object-oriented?
Yes.
| (That code appears in libalgebra distributed with Aldor and it
| basically provides a generic function that given a function "f: R ->
| S" returns a function "map(f)" of type "RX -> SX" that applies "f" on
| the coefficients of a univariate polynomial.)
|
| UnivariateFreeRing2(
| R : Join(ArithmeticType, ExpressionType),
| RX: UnivariateFreeRing R,
| S : Join(ArithmeticType, ExpressionType),
| SX: UnivariateFreeRing S
| ): with {
| map: (R -> S) -> RX -> SX;
| } == add {
| map(f:R -> S)(p:RX):SX == {
| q:SX := 0;
| for term in p repeat {
| (c, n) := term;
| q := add!(q, f c, n);
| }
| q;
| }
| }
|
| What is the class and what are the methods?
The class is the collection of "things" that you can "pretend" to be
univariate polynomials.
Oh, I think that is wrong. The "univariate polynomials" come as a
parameter and have nothing to do with UnivariateFreeRing2.
As Bill mentioned, if that is considered to be a class, then it has no
instantiations. It's a package in "Axiom" terms.
Post by Gabriel Dos Reis
| Sorry that I don't know CLOS,
The reason why I mention CLOS is that it is close to Lisp (given the
general topic of this mailing list :-),
Oh, if LISP is the general topic of this mailing list, then I should be
quiet. ;-)
Post by Gabriel Dos Reis
| BTW, I don't say that Aldor hasn't some kind of object-orientation,
| but it is in my opinion not a pure object-oriented language.
My view is that debates of "pure" <your-favorite-buzzword> are
meaningless as far as productive system building is concerned.
So, I will stop here.
Right. I'll also stop.

Ralf
Gabriel Dos Reis
2006-02-21 11:57:12 UTC
Permalink
Ralf Hemmecke <***@hemmecke.de> writes:

| On 02/20/2006 10:02 PM, Gabriel Dos Reis wrote:
| > Ralf Hemmecke <***@hemmecke.de> writes:
| > | Hmm, do you call the following object-oriented?
| > Yes.
| > | (That code appears in libalgebra distributed with Aldor and it
| > | basically provides a generic function that given a function "f: R ->
| > | S" returns a function "map(f)" of type "RX -> SX" that applies "f" on
| > | the coefficients of a univariate polynomial.)
| > | | UnivariateFreeRing2(
| > | R : Join(ArithmeticType, ExpressionType),
| > | RX: UnivariateFreeRing R,
| > | S : Join(ArithmeticType, ExpressionType),
| > | SX: UnivariateFreeRing S
| > | ): with {
| > | map: (R -> S) -> RX -> SX;
| > | } == add {
| > | map(f:R -> S)(p:RX):SX == {
| > | q:SX := 0;
| > | for term in p repeat {
| > | (c, n) := term;
| > | q := add!(q, f c, n);
| > | }
| > | q;
| > | }
| > | }
| > | | What is the class and what are the methods?
| > The class is the collection of "things" that you can "pretend" to be
| > univariate polynomials.
|
| Oh, I think that is wrong.

I don't think so.

| The "univariate polynomials" come as a
| parameter and have nothing to do with UnivariateFreeRing2.

Not quite. "Univariate polynomial" is a bundle of methods, whether it
is a parameter database or a global database is largely irrelevant.
What is relevant is the structure it exposes both interface and
overridable functions.

-- Gaby
Doug Stewart
2006-02-20 21:16:12 UTC
Permalink
<snip>
Wow!!! I have been watching and learning Axiom for the last two months,
and this thread has really help me.
What I have found is that I can pick up Axiom in a simple way quite
quickly but then I hit a wall that I could not seem to get past.

This thread has brought to light what the wall is and has help me muchly.
Could someone in the know take some material from this thread and use it
in the manual?
I know that just reading this has opened my eyes.

Doug Stewart
Bill Page
2006-02-19 21:11:02 UTC
Permalink
Martin,
Post by Martin Rubey
Post by Bill Page
Since DMP is the highest level domain constructor, I would
expect it to interpret 'x' as being in the polynomial domain
first and only if forced treat is as being in the underlying
coefficient domain.
I believe that this is not always the case, although I don't
have an example at hand.
That is why we need some proper and detailed documentation.
Failing that, we can always read and analyze the source code.
(Actually, it order to write such documentation we have to
do this anyway.)
Post by Martin Rubey
However, I would like to restate what William Sit and I were
Axiom is able to deal (more or less) properly with
variables bearing the same name but having different
meanings.
Yes! I agree, except I having looked at a lot of source code
I would no longer feel the need to "hedge my bets" by adding
"more or less". I think it can always deal properly with this
situation. If we find some situation where it does not, then
we should treat this as a bug and correct it.
Post by Martin Rubey
We did not agree on whether we should allow this to happen
or not...
There may be some situations, such as in the Axiom interpreter
where you might wish to warn the user about the sometimes
unexpected consequences of domains that allow this. But I
completely disagree with the suggestion that is should not
be allowed.
Post by Martin Rubey
Post by Bill Page
b := monomial(x,[0,0]::DirectProduct(2,NNI))$P
Can you explain this result?
(23) -> degree b
(23) [0,0]
Type: DirectProduct(2,NonNegativeInteger)
(24) -> b+x
(24) x + x
DistributedMultivariatePolynomial([x,y],Expression Integer)
Here, we have two *different* "variables", the only happen to
bear the same name.
No. That is the wrong analysis. Axiom does not have any concept
of "variable" that would allow you to make this statement without
first giving the context of the domain. By definition the members
of two different domains are *different* by the very nature of
belonging to two different domains. But in the right context
(right domain) we can see in fact that the two 'x' above are in
fact the same symbol but used to two different contexts. The DMP
domain explicitly makes the distinction between polynomial
variables and coefficients. It thus provides the context where
the two uses of 'x' can be distinguished when the coefficient
domain includes expressions containing the symbol 'x'.
Post by Martin Rubey
What I consider very problematic is, that
(b+x)::EXPR INT
gives 2x. I believe that this can lead to very "surprising"
results.
This is only surprising if one does not understand the meaning
of expression 'x+x' in (24). Part of the reason for the confusion,
I think, is because the common OutputForm for polynomials does
not typographically identify polynomial variables versus
coefficients. But if, say the polynomial variables were always
printed in bold face roman type but the coefficients were
printed in italic, it might be more clear what is going on.
Post by Martin Rubey
In any case, I think it is better not to use such types.
I think it would be better to document clear how and when
such types should be used.
Post by Martin Rubey
Currently, this is not always possible, it would be necessary
to introduce a parametrized Expression domain, that takes
variables as parameters -- this is on the WishList, by the
way. I don't think it would be too much work.
This might be interesting, but I am not completely convinced. In
fact, I sometimes wonder whether it makes sense to distinquish
the coefficient domain in the case of Expressions.

Regards,
Bill Page.
Martin Rubey
2006-02-19 21:45:03 UTC
Permalink
Post by Bill Page
Post by Bill Page
b := monomial(x,[0,0]::DirectProduct(2,NNI))$P
Can you explain this result?
(23) -> degree b
(23) [0,0]
Type: DirectProduct(2,NonNegativeInteger)
(24) -> b+x
(24) x + x
DistributedMultivariatePolynomial([x,y],Expression Integer)
Here, we have two *different* "variables", the only happen to
bear the same name.
No. That is the wrong analysis. Axiom does not have any concept of "variable"
that would allow you to make this statement without first giving the context
of the domain.
We agree, only I did not express myself clearly enough -- obviously, the
quotation marks did not suffice. I should have written: ... two different
"things" ...
Post by Bill Page
What I consider very problematic is, that
(b+x)::EXPR INT
gives 2x. I believe that this can lead to very "surprising"
results.
This is only surprising if one does not understand the meaning of expression
'x+x' in (24).
Don't worry, I don't find it surprising. In fact, I wrote that it could *lead*
to "surprising" results. I.e., I could imagine that some innocent looking
computation would not be correct in the situation above. For example,

differentiate(b+x,x)

gives one, but

differentiate(b+x,x)@EXPR INT

gives two. Note that I did not even need to ask to coerce b+x to EXPR INT... Of
course, as we are discussing this now, this does not come as a surprise. But I
bet that even for quite an experienced axiom user, who did not follow this
thread for some reason, it will be difficult to spot the mistake. Especially if
he doesn't realize that she wanted to compute something else...
Part of the reason for the confusion, I think, is because the common
OutputForm for polynomials does not typographically identify polynomial
variables versus coefficients. But if, say the polynomial variables were
always printed in bold face roman type but the coefficients were printed in
italic, it might be more clear what is going on.
I think that this is a very nice idee. I guess this could be even realized on
text terminals, couldn't it?

Martin
Ralf Hemmecke
2006-02-20 16:12:22 UTC
Permalink
Post by Martin Rubey
Part of the reason for the confusion, I think, is because the common
OutputForm for polynomials does not typographically identify polynomial
variables versus coefficients. But if, say the polynomial variables were
always printed in bold face roman type but the coefficients were printed in
italic, it might be more clear what is going on.
I think that this is a very nice idee. I guess this could be even realized on
text terminals, couldn't it?
I hope nobody is constructing something like

DMP([x], DMP([x], DMP([x], Integer)))

What are the possible typefaces of x?

Ufff... what's that???

P := DMP([x], DMP([x], Integer))
a:P := x
DistributedMultivariatePolynomial([x],
DistributedMultivariatePolynomial([x],Integer)) is not a valid
type.

Why would Axiom forbid P and allow
Q := DMP([x], Polynomial Integer)
b:Q := x
(6) x
Type: DistributedMultivariatePolynomial([x],Polynomial Integer)

???

And why is that???

(15) -> R := Polynomial Polynomial Integer

(15) Polynomial Polynomial Integer
Type:
Domain
(16) -> c: R := x

Polynomial Polynomial Integer is not a valid type.

Yes, now I do my homework and look into the sources of DMP.
Well, my understanding of SPAD is a bit limited, but DMP builds on
GeneralDistributedMultivariatePolynomial (GDMP) and I cannot find
anything that looks like aborting the domain instantiation.

So let's do the following...
Copy the code from DistributedMultivariatePolynomial and just rename the
domain.

--begin aaa.spad
)abbrev domain RHX RHXPolynomial

RHXPolynomial(vl,R): public == private where
vl : List Symbol
R : Ring
E ==> DirectProduct(#vl,NonNegativeInteger)
OV ==> OrderedVariableList(vl)
public == PolynomialCategory(R,E,OV) with
reorder: (%,List Integer) -> %
private ==
GeneralDistributedMultivariatePolynomial(vl,R,E)
--end aaa.spad

Then say
)compile aaa.spad
P := RHX([x], RHX([x], Integer))
a:P := x

(2) x
Type: RHXPolynomial([x],RHXPolynomial([x],Integer))

Hmm, just by renaming of DMP to RHX I get a different behaviour?
This tells me that I don't have to look into the Algebra sources to find
why DMP([x], DMP([x], Integer)) is not a valid type. :-(

I hope at some point you agree with me that the interpreter or whoever
forbids to construct DMP([x], DMP([x], Integer)) ) should NOT add
knowledge that is not derivable from the SPAD code in Algebra.

Ralf
Francois Maltey
2006-02-20 09:52:31 UTC
Permalink
"Bill Page" <***@synthesis.anikast.ca> propose :

((***))
Post by Bill Page
There may be some situations, such as in the Axiom interpreter
where you might wish to warn the user about the sometimes
unexpected consequences of domains that allow this.
I agree with this,

For students and I a lot of problems are about :
<< You think that 2 objects are identical if their writing are identical. >>

The 2 way to read the x is logical when we think as axiom,
but is a trap for students who use computer algebra for solving
a mathematical exercice.
Post by Bill Page
But really it is very simple and easy to predict. The problem
is that most people focus is on the wrong thing. This is especially
natural if they have previous experience with other computer algebra
systems.
But almost all my student use derive or maple or a TI-9? for little
computation, and during their mathematical studies they don't learn
object programming. So it's impossible to say :
<< learn axiom from the emptyset. >>

I like mupad because easy computation was easy to type,
but difficult idea can be done with clever idea about Domains.
I hope that axiom should have the same point of view.

I don't like maple which have very often wrong results because it's impossible
to have type : In maple the fact that 0.0 = 0 gives very surprising result.
So I prefer explain mupad that axiom to my student, because if I don't
have this error I can do a more difficult exercice.
Post by Bill Page
I could imagine that some innocent looking
computation would not be correct in the situation above.
As Martin I already imagine this error :

P := DMP ([x,y], EXPR INT)
a :P := x
b := a/x

differentiate(b,x) -- 1/x
differentiate(b+x,x)@EXPR INT -- 0

I find it's a wonderful idea ((***)) to have an error or a warning during
b := a/x. It's really possible ?

Bill, I don't want to change all the axiom language ;-)
it's the _only_ trap I see in the interpeter.

The other computation are logical for students in mathematics. ;-)
And if a student can understand the coefficient function, he can understand
why it's a silly computation to type monomial (x, [0,0]...)
Bill you think it's must remain possible, why not.

Have a good day !

François
Bill Page
2006-02-20 03:37:24 UTC
Permalink
Francois,
Post by Ralf Hemmecke
P := DistributedMultivariatePolynomial([x,y],Expression Integer)
a: P := x
a/x
Axiom replies:

(3) -> a/x

1
(3) - x
x
Type: DistributedMultivariatePolynomial([x,y],Expression Integer)
Post by Ralf Hemmecke
However, I guess, most people find this confusing.
Indeed...
But really it is very simple and easy to predict. The problem
is that most people focus is on the wrong thing. This is especially
natural if they have previous experience with other computer algebra
systems.

In Axiom it is necessary to first understand the meaning of the
domain:

DistributedMultivariatePolynomial([x,y],Expression Integer)

What kind of operations does it export? You can ask Axiom:

)sh DistributedMultivariatePolynomial([x,y],Expression Integer)

After that one can consider if and how the expression a/x might
be a member of this domain.
Why axiom doesn't see the denominator as a DMP([x,y], Expr Int) ?
The numerator is a DMP([x,y], Expr Int).
Already your question tells me that you are not thinking about
the domain first. An expression which has both a numerator and
a denominator can not be member of the domain DMP(...)
Numerator and denominator of any fraction are in the same ring,
and have the same type.
But the expression 'a/x' is not a fraction. It is a binary
operation that involves 'a' and 'x'. Axiom needs to know what the
'/' represents. To do this it has to match the types of it's
arguments to the signature of a known function. The type of 'a'
is known, Axiom starts by assuming that x is of type Variable
and looks for an operation '/' in DMP with arguments DMP and
Variable, but there is none. Then it looks for the same operation
in Variable and finds none. So next it considers the operation
'/' with signature

/ : (%, Expression Integer) -> %

in DMP. (Note that % means "this domain".) The Axiom interpreter
discovers that it can first coerce the 'x' of type Variable to an
'x' of type Expression Integer, then it can apply the above operation
from DMP. The result is still something in DMP which happens to have
'x' as both the polynomial variable and '1/x' as it's coefficient.
The implementation of DMP is such that it does not attempt to
simply this result - the polynomial variables and the coefficient
domain remain separate.
The x variable can't be a variable of the Expression Integer Ring,
because this a is one of the polynomial.
There are two separate uses of the variable x: once as a polynomial
variable in DMP and once in the '1/x' which is in the domain
Expression Integer. These are the *same* variable, but used in
two different ways (i.e. in two different domains).
// 1 //
I was waiting that axiom read a/x as (a::P)/(x::P) because I wait
the same calculus from my students on a sheet of paper.
This result is easy to obtain and if I was a teacher of computer
algebra, I would probably leave it as an exercise for my students.
:) But this is not a classroom. The answer is almost given in the
way you wrote the question. Try this:

(4) -> b: FRAC P :=x

(4) x
Type: Fraction DistributedMultivariatePolynomial([x,y],Expression
Integer)

(5) -> b/x

(5) 1
Type: Fraction DistributedMultivariatePolynomial([x,y],Expression
Integer)
Is it too difficult ?
I think it is very simple, but my explanation is too long. :)
// 2 //
b := monomial(x,[0,0]::DirectProduct(2,NNI))$P
I understand what is R[X], (R[X])[Y], (R[Y])[X], R[X,Y] and R[Y,X].
I don't understand what is (R[X])[X], so axiom might forget it.
Axiom understands (because of the implementation of DMP) the
distinction between the use of 'x' as a polynomial variable and
the use of 'x' as a coefficient. Perhaps it is true that such a
distinction is not commonly made in mathematics, but the
implementation of DMP keeps these uses distinctly separate.
Axiom is not able to "forget it".
.....
All domains that contain variables need to export a function
if S has variables2: S -> List Symbol then
variables2: % -> List Symbol
variables2 f ==
merge(variables2(numer(f)), variables2(denom(f)))
if R has variables2: R -> List Symbol then
coerce(r:R):% ==
if member?(x, variables2(r)) then
error "coefficient contains variable"
else coerce(r)$Rep
......
The patch is not interesting because this situation does not
represent an error. It is a situation that Axiom was designed
to handle correctly. The facilities already exist in Axiom to
simplify the polynomial

1
- x
x

(where '1/x' is a coefficient and the right hand 'x' is the
polynomial variable), if it is desirable.
// 3 //
Why DMP doesn't accept OrderedSet but only List Symbol ?
I think this difference is only a historical accident and the
fact that the work on different polynomial domains was done at
different times by different people.
* one writes a new domain with a new representation. For
'DistributedExpression' I failed to do so, since the proper
representation would be 'DMP', but this only accepts a 'List Symbol'
as variables, for expressions I need to allow an arbitrary
'OrderedSet' however.
Perhaps you can send a copy of your source code. I think what
you are trying to do is possible but it might turn out to be
rather complicated. You can however quite easily convert between
an OrderedSet of variables and a list of variables.
If I'm right Expression are built over POLY which accept
OrderedSet or <<kernel>> as sin x and so.
I am afraid that Expression is much more complicated. :( In
fact it is one of the most complex domains in Axiom. I agree,
however with you and Martin Rubey, that we need to re-consider
this domain and possibly extend it in various ways.

I hope that in spite this email is too long, perhaps it is
some use to you.

Regards,
Bill Page.
Bill Page
2006-02-20 17:26:25 UTC
Permalink
Post by Francois Maltey
...
<< You think that 2 objects are identical if their writing
are identical. >>
The 2 way to read the x is logical when we think as axiom,
but is a trap for students who use computer algebra for
solving a mathematical exercise.
I agree that Axiom could be improved by using a more rich
output format for complex constructions. Of course when Axiom
was originally designed the computer output devices where not
so advanced - it was exciting then just to print an integral
sign on an ASCII terminal, however bad it looked. Now we can
produce much richer output directly from LaTeX on the computer
screen that would be less ambiguous and easier to read.

But really I do not expect a complicated domain such:

DMP([x,y],EXPR INT)

to be of much use to beginning students. Usually either 'POLY INT'
or 'EXPR INT' are enough. I proposed it to you because you were
interested in re-programming the package TRMANIP to perform
better trigonometric expansions. In that case it would be used
only internally in the coding of these expansions.
Post by Francois Maltey
Post by Bill Page
But really it is very simple and easy to predict. The problem
is that most people focus is on the wrong thing. This is
especially natural if they have previous experience with
other computer algebra systems.
But almost all my student use derive or maple or a TI-9? for
little computation, and during their mathematical studies they
<< learn axiom from the emptyset. >>
I don't think it is necessary to learn object-oriented
programming in order to *use* Axiom - at least, I agree that
it should not be necessary. Axiom was designed and implemented
most of the ideas about categories and domains before computer
science even considered the concept. Axiom actually implemented
some fairly common abstract mathematical ideas about "domains"
which you still see in the formal definitions of mathematical
objects like moniods, groups etc. And it extended these ideas in
a logical way that in the end is similar (not identical) to
modern ideas about object-oriented programming. But now perhaps,
the computer science student has an earlier introduction to
these sort of abstractions than the mathematics student.

A side comment: It often seems to me that both theoretical
physics and computer science take mathematics "more seriously"
than the mathematicians themselves. You can see this to the
extent to which so called "pure mathematics" is actually
*applied* in these subjects. In promoting computer algebra to
mathematicians we are sometimes in the odd situation of trying
to sell these "mathematical" ideas back to their originators. :)
Post by Francois Maltey
I like mupad because easy computation was easy to type,
but difficult idea can be done with clever idea about Domains.
I hope that axiom should have the same point of view.
Unfortunately, I have to agree that Axiom does not do a good
job of this. The designers of Axiom were aware of this problem
and that is one reason why there was a proposed to develop a
new interpreter for Axiom called B# (B natural) which would
provide an initially much more intuitive user interface for
new users. Unfortunately the research funding for Axiom ran
out, before these ideas could be realized. I think it would
be great if someday the open source Axiom project could
resurrect this work.
Post by Francois Maltey
Post by Bill Page
I could imagine that some innocent looking computation
would not be correct in the situation above.
P := DMP([x,y], EXPR INT)
a :P := x
b := a/x
differentiate(b,x) -- 1/x
(4) -> differentiate(b,x)

1
(4) -
x
Type: DistributedMultivariatePolynomial([x,y],Expression Integer)

I think this result should be classed a bug. The 'differentiate'
operation apparently makes some incorrect assumptions about the
coefficient domain. I think the result should be the same as:

(5) -> differentiate(b::EXPR INT,x)::P

(5) 0
Type: DistributedMultivariatePolynomial([x,y],Expression Integer)

So we should create a bug report in

http://wiki.axiom-developer.org/IssueTracker
For this I get:

(6) -> differentiate(b+x,x)@EXPR INT

(6) 1
Type: Expression Integer

which seems correct to me.
Post by Francois Maltey
I find it's a wonderful idea ((***)) to have an error or a
warning during b := a/x. It's really possible ?
Yes. I think Martin's proposed code could be easily changed
to give a warning, but in some cases (e.g. in the case of
using this type of construction inside the TRMANIP package)
I think this warning could cause some confusion. So I think
it would be better do in the Axiom interpret code rather than
in the definition of the domain itself.
Post by Francois Maltey
Bill, I don't want to change all the axiom language ;-)
it's the _only_ trap I see in the interpreter.
I am sure that there are other traps... ;-) I am not against
changing the "axiom language", for example I mentioned B# above,
but do I think we have to be very careful when we consider changes
to Axiom's mathematical library. The library is large, complex,
poorly documented, and based on some theories that are barely more
than research ideas. Even small changes might have large unexpected
consequences. But still, I would claim that Axiom is superior to
most other computer algebra systems in this regard - that is how
bad the situation is with some of these other systems!
Post by Francois Maltey
The other computation are logical for students in mathematics. ;-)
And if a student can understand the coefficient function, he
can understand why it's a silly computation to type
monomial(x, [0,0]...)
Bill you think it's must remain possible, why not.
What might seem silly in some situations might be sensible
in other situations.

Regards,
Bill Page.
Ralf Hemmecke
2006-02-21 09:26:29 UTC
Permalink
Post by Bill Page
Post by Francois Maltey
Post by Bill Page
I could imagine that some innocent looking computation
would not be correct in the situation above.
P := DMP([x,y], EXPR INT)
a :P := x
b := a/x
differentiate(b,x) -- 1/x
(4) -> differentiate(b,x)
1
(4) -
x
Type: DistributedMultivariatePolynomial([x,y],Expression Integer)
I think this result should be classed a bug. The 'differentiate'
operation apparently makes some incorrect assumptions about the
(5) -> differentiate(b::EXPR INT,x)::P
(5) 0
Type: DistributedMultivariatePolynomial([x,y],Expression Integer)
Well, Bill, imagine you had to programm DistributedMultivariatePolynomial.
In gdpoly.spad we see

differentiate(p: %,v: OV) ==
multivariate(differentiate(univariate(p,v)),v)

where univariate just converts p to an element of
SparseUnivariatePolynomial(%). (BTW, that's already a trick!)
However, it seems the most obvious thing to do.

Now you suggest to do that differently, since the coefficients of that
univariate polynomial might also contain the variable x. Well, would be
possible, but obviously the designer of DMP (or rather GDMP) did not
think of such a strange thing like having the same variable as the
indeterminate of the polynomial and at the same time in the domain of
coefficients.

Still, it's a bug, because that behaviour should at least be very vell
documented. It is, however, not so clear where to do this. I suggest
there should be a note in DMP rather than the category
PartialDifferentialRing (where the signature comes from).

Ralf
Martin Rubey
2006-02-22 08:54:21 UTC
Permalink
Dear Bill, Ralf, *

I'm currently out of time. But I'm a little afraid of the direction the
discussion takes currently.

I believe that the intension of a constructor like DMP is to cover
*polynomials*.

If we allow (2*x+1/x)::DMP([x], EXPR INT), i.e., allowing 1/x as a coefficient,
then it must be clear that the "x" in 1/x is something different than the "x"
in 2*x. Otherwise we don't get a polynomial, obviously.

So, I think that
Post by Bill Page
Post by Francois Maltey
P := DMP([x,y], EXPR INT)
a :P := x
b := a/x
differentiate(b,x) -- 1/x
(4) -> differentiate(b,x)
1
(4) -
x
Type: DistributedMultivariatePolynomial([x,y],Expression Integer)
I think this result should be classed a bug. The 'differentiate'
operation apparently makes some incorrect assumptions about the
is not a bug. If you want to have axiom output 0, then I imagine that you will
get into trouble with writing packages, variable capture might well occur.

I'd rather say that b::EXPR INT giving one is troublesome. I wouldn't really
classify it as a bug though, given the nature of EXPR INT. Note that b::UP([x],
INT) or b::POLY INT give errors!

PLEASE don't change the behaviour of DMP and company. What should be documented
(and I think Ralf did, but I hadn't time) is that domains like POLY EXPR INT
and friends can lead to "surprising" results. This should go into the section
"types" of the axiom book.

Martin
Bill Page
2006-02-20 19:02:25 UTC
Permalink
Post by Gabriel Dos Reis
[...]
| > But eventually in order to program in Axiom, it is
| > essential that they gain a full appreciation of the
| > object-oriented design philosophy.
|
| I would not really like to call Axiom (or Aldor) object-oriented.
| We don't write
|
| a.add(b)
|
| in order to add two numbers.
There is more to object-orientation than "dot notation". To my
eyes and mind, Aldor and Axiom are object-oriented, and they
haven't yet escaped that land :-(
I am curious why you wrote :-( ? Are you implying that you wish
that Aldor and Axiom did use a paradigm more advanced than object
orientation?
Hmm, do you call the following object-oriented?
Before discussing whether something is "object-oriented" or not
I think we need to agree on a definition. For example, I think
the following definition is quite good:

http://www.webopedia.com/TERM/O/object_oriented_programming_OOP.html

object-oriented programming

A type of programming in which programmers define not only the
data type of a data structure, but also the types of operations
(functions) that can be applied to the data structure. In this way,
the data structure becomes an object that includes both data and
functions. In addition, programmers can create relationships
between one object and another. For example, objects can inherit
characteristics from other objects.

One of the principal advantages of object-oriented programming
techniques over procedural programming techniques is that they
enable programmers to create modules that do not need to be
changed when a new type of object is added. A programmer can
simply create a new object that inherits many of its features
from existing objects. This makes object-oriented programs easier
to modify.

This definition seems to apply directly to Axiom and Aldor.

BTW, I think the wikipedia definition on the other hand is
terrible!

http://en.wikipedia.org/wiki/Object-oriented_programming
(This code appears in libalgebra distributed with Aldor and
it basically provides a generic function that given a function
"f: R -> S" returns a function "map(f)" of type "RX -> SX" that
applies "f" on the coefficients of a univariate polynomial.)
UnivariateFreeRing2(
R : Join(ArithmeticType, ExpressionType),
RX: UnivariateFreeRing R,
S : Join(ArithmeticType, ExpressionType),
SX: UnivariateFreeRing S
): with {
map: (R -> S) -> RX -> SX;
} == add {
map(f:R -> S)(p:RX):SX == {
q:SX := 0;
for term in p repeat {
(c, n) := term;
q := add!(q, f c, n);
}
q;
}
}
What is the class and what are the methods?
Clearly 'UnivariateFreeRing2' is the class and 'map' is a method.
No?

In Axiom terminology this would be called a "package" since it
does not involve any representation object (Rep) and so does
not have any instances (members).

Axiom and Aldor actually implement a two-level class structure
so 'UnivariateFreeRing2' itself is an instance of the class
(category) 'with { map: (R -> S) -> RX -> SX; }'.

Just curious: The syntax:

map(f:R -> S)(p:RX):SX == {...

looks strangely abbreviated to me. Why not write:

map(f:R -> S):RX->SX ==

(p:RX):SX +-> { ...

Is this equivalent?
Can you write that in JAVA or CLOS? I would be happy to see it.
Ignoring for now the details of the Aldor library, why would you
expect this to be difficult? Java supports functions that return
functions anc CLOS is just common lisp done a certain way, so
surely there is no question. Am I missing something?
Post by Gabriel Dos Reis
| the function "add" is not attached to the object a. It is
| rather that a and b are on equal footing.
"equal footing" is not contradictory to object orientation.
Well, you may be right. But when I read about implementation
of complex numbers in C++ and saw that a.add(b) construct,
I really did not like it (at least not in the context of mathematics).
It is saying: sent the message "add" with parameter "b" to the
object "a". And it means that "a" has to do the work since "a"
knows how to add something to itself. It is like saying. The
integer 1 knows how another integer can be added to it. I don't
consider that thinking to be quite natural in the context of
mathematics. I agree, object-orientation be appropriate for other
contexts.
What you describe should probably called a "message passing"
paradigm as opposed to object-oriented, as such. Because SmallTalk
was one of the first well known object-oriented languages and
it also implemented the message passing paradigm, I think these
two programming methodologies are sometimes confused.

I Axiom if I write;

a:Complex Integer := 1
a + 2

the operation '+' is taken from the domain of 'a'. Both 'a' and
'2' an instances of the class (domain) 'Complex Integer'.
Post by Gabriel Dos Reis
| then it becomes clear that Axiom has more to offer that the
| current trend in programming.
The current trend in programming is some heavy or displaced
emphasis on generic programming.
Sorry that I don't know CLOS, but I have looked a bit into JAVA's
generics. And that is a lot weaker than what was already available
in Aldor several years ago.
I think that is true and these ideas originated in Axiom itself,
which very considerably pre-dates "current trends in programming".
I think it is a pity that Axiom was/is not better known among
programming language designers.
BTW, I don't say that Aldor hasn't some kind of object-orientation,
but it is in my opinion not a pure object-oriented language.
Define 'pure' ... ;)

Regards,
Bill Page.
Gabriel Dos Reis
2006-02-20 21:22:27 UTC
Permalink
"Bill Page" <***@synthesis.anikast.ca> writes:

| On February 20, 2006 12:57 PM Ralf Hemmecke wrote:
| >
| > On 02/20/2006 06:15 PM, Gabriel Dos Reis wrote:
| > > Ralf Hemmecke <***@hemmecke.de> writes:
| > >
| > > [...]
| > > | Bill Page wrote:
| > > | > But eventually in order to program in Axiom, it is
| > > | > essential that they gain a full appreciation of the
| > > | > object-oriented design philosophy.
| > > |
| > > | I would not really like to call Axiom (or Aldor) object-oriented.
| > > | We don't write
| > > |
| > > | a.add(b)
| > > |
| > > | in order to add two numbers.
| > >
| > > There is more to object-orientation than "dot notation". To my
| > > eyes and mind, Aldor and Axiom are object-oriented, and they
| > > haven't yet escaped that land :-(
| >
|
| I am curious why you wrote :-( ? Are you implying that you wish
| that Aldor and Axiom did use a paradigm more advanced than object
| orientation?

yes, more or less.

Many linguistic constructs one finds in Aldor and Axiom have been the
"lead" at the time (at least two decades ago, though neither Aldor nor
Axiom were called that way at the time) -- blending object orientation
(in the style of categories and domains) and imperative higher order
programming was rather powerful and "unique". However, I'm kind of
"disappointed" to see that virtual no progress has been since then.
On the other hand, qualified type systems have emerged leading more
"natural" expression of ideas (though posing more difficult
challenges), and I'm sorry to say it, and we are here comparing Axiom
to Java :-(

| > Hmm, do you call the following object-oriented?
|
| Before discussing whether something is "object-oriented" or not
| I think we need to agree on a definition. For example, I think
| the following definition is quite good:
|
| http://www.webopedia.com/TERM/O/object_oriented_programming_OOP.html

I agree that it captures many points of what I would consider "object
oriented".

[...]

| I Axiom if I write;
|
| a:Complex Integer := 1
| a + 2
|
| the operation '+' is taken from the domain of 'a'. Both 'a' and
| '2' an instances of the class (domain) 'Complex Integer'.

Exactly! If you look at "type classes", you'll see that is exactly
what is happening. In mundain terms, the operation is extracted from
the "vtable", which is guaranteed by the fact that:

* the category says the operation exists (<-> abstract classes or
interfaces).

* the domain says it implements the operation.

[...]

| I think that is true and these ideas originated in Axiom itself,
| which very considerably pre-dates "current trends in programming".
| I think it is a pity that Axiom was/is not better known among
| programming language designers.

That was part my point. The other part is that it is pity Axiom
designers did not keep the lead on that front.

In April 2004, there was a workshop organized at Adobe (San Jose) to
talk about "concepts for C++". I deliberately chosed to present two
"main" type systems: (1) type classes, and (2) "categories and
domains" in Aldor. That was also an opportunity for me to foster a
deeper understand of the ideas work in both world (and later build
an excuse of why I did not push for them :-).

The linguistic construct I found the most useful in Aldor is "post
facto extension".

-- Gaby
Ralf Hemmecke
2006-02-21 11:33:54 UTC
Permalink
Post by Bill Page
UnivariateFreeRing2(
R : Join(ArithmeticType, ExpressionType),
RX: UnivariateFreeRing R,
S : Join(ArithmeticType, ExpressionType),
SX: UnivariateFreeRing S
): with {
map: (R -> S) -> RX -> SX;
} == add {
map(f:R -> S)(p:RX):SX == {
q:SX := 0;
for term in p repeat {
(c, n) := term;
q := add!(q, f c, n);
}
q;
}
}
Can you write that in JAVA or CLOS? I would be happy to see it.
Ignoring for now the details of the Aldor library, why would you
expect this to be difficult? Java supports functions that return
functions ...
I'm not so fluent in JAVA, but take for example a semigroup.
Can you do such simple thing as giving an interface for it in JAVA.

define Monoid: Category == with {
1: %
*: (%, %) -> %
}

The problem is the "1: %" as a constant (not a nullary function).
An abstract class is no solution since, we might need multiple
inheritance from various interfaces (imagine to build a Ring afterwards).

Maybe it works to translate UnivariateFreeRing2 to JAVA, but I guess the
code will look terribly complicated if it incorporates the conditions on
R and RX, S and SX. Yes, JAVA generics are allowed.
(Well, I shut up, that is not a mailing list about JAVA.)

Ralf
Gabriel Dos Reis
2006-02-21 11:53:35 UTC
Permalink
Ralf Hemmecke <***@hemmecke.de> writes:

| The problem is the "1: %" as a constant (not a nullary function).

The distinction is largely syntactic, not fundamental.

-- Gaby
Ralf Hemmecke
2006-02-21 12:01:53 UTC
Permalink
Post by Gabriel Dos Reis
| The problem is the "1: %" as a constant (not a nullary function).
The distinction is largely syntactic, not fundamental.
I was once told that in Aldor the difference between
a: %
and
b: () -> %
is that
b() will run a program which might side-effect other things or even
return something different each time.

Ralf
Gabriel Dos Reis
2006-02-21 17:11:38 UTC
Permalink
Ralf Hemmecke <***@hemmecke.de> writes:

| > | The problem is the "1: %" as a constant (not a nullary function).
| > The distinction is largely syntactic, not fundamental.
|
| I was once told that in Aldor the difference between
| a: %
| and
| b: () -> %
| is that
| b() will run a program which might side-effect other things or even
| return something different each time.

yes, if the body of b() is defined so. But not all b() are affected
by that artifact. But it is not a fundamental or intrinsic
distinction that would have to cary to other languages.

-- Gaby
Gabriel Dos Reis
2006-02-21 23:21:37 UTC
Permalink
Ralf Hemmecke <***@hemmecke.de> writes:

| > | The problem is the "1: %" as a constant (not a nullary function).
| > The distinction is largely syntactic, not fundamental.
|
| I was once told that in Aldor the difference between
| a: %
| and
| b: () -> %
| is that
| b() will run a program which might side-effect other things or even
| return something different each time.

expanding on my preivous answer, have a look at the section 5.2 os the
Aldor user guide on literal forming -- you can define your own function
to interpret a string literal as a constant.

-- Gaby
Ralf Hemmecke
2006-02-22 10:57:10 UTC
Permalink
Post by Gabriel Dos Reis
| > | The problem is the "1: %" as a constant (not a nullary function).
| > The distinction is largely syntactic, not fundamental.
|
| I was once told that in Aldor the difference between
| a: %
| and
| b: () -> %
| is that
| b() will run a program which might side-effect other things or even
| return something different each time.
expanding on my preivous answer, have a look at the section 5.2 os the
Aldor user guide on literal forming -- you can define your own function
to interpret a string literal as a constant.
I knew about this Literal stuff before...

http://lists.gnu.org/archive/html/axiom-developer/2006-02/msg00154.html

But as you see, if you write a domain that has a function
string: Literal -> %,
it is a function and that means that "1" and "1" need not give identical
values.

The following program prints 11 and 12.

-- aldor -laldor -grun domaintest.as
--BEGIN domaintest.as
#include "aldor"
DomainTest: with {
integer: Literal -> %;
coerce: % -> Integer;
} == add {
Rep == Integer;
local n: Integer := 0;
integer(l: Literal): % == {
i: Integer := integer(l)$Integer;
free n := n + 1;
per (i + n);
}
coerce(x: %): Integer == rep x;
}
main(): () == {
import from TextWriter, Character, Integer;
a: DomainTest := 10;
b: DomainTest := 10;
stdout << (a::Integer) << newline;
stdout << (b::Integer) << newline;
}
main();
Ralf Hemmecke
2006-02-22 16:01:42 UTC
Permalink
Dear Gaby,
| > | > | The problem is the "1: %" as a constant (not a nullary
| > function).
| > | > The distinction is largely syntactic, not fundamental.
| > | | I was once told that in Aldor the difference between
| > | a: %
| > | and
| > | b: () -> %
| > | is that
| > | b() will run a program which might side-effect other things or even
| > | return something different each time.
| > expanding on my preivous answer, have a look at the section 5.2 os
| > the
| > Aldor user guide on literal forming -- you can define your own function
| > to interpret a string literal as a constant.
|
| I knew about this Literal stuff before...
I have no doubt about that :-)
| http://lists.gnu.org/archive/html/axiom-developer/2006-02/msg00154.html
|
| But as you see, if you write a domain that has a function
| string: Literal -> %,
| it is a function and that means that "1" and "1" need not give
| identical values.
yes, that is precisely why I said in an earlier message that the
distinction is largely syntactic. it is not something fundamental in
the context of your discussion about axiom and o stuff.
Underneath, everything is a function in Aldor!
Well, it might depend on which level you look at it. If the generated C
code is concerned, I have no idea about that.

But if it were really just syntactic, then the output given below is
strange.

However, this behaviour is exactly, the difference between a constant
and a nullary function in Aldor.

Aldor computes the value for x at the time the domain is instantiated.
So it is constant over the lifetime of the domain (unless some dirty
tricks change that value). For y it is different. That is a function
constant. But a constant of type ()->% not of type %. Now, of course, if
you say "y()", you get something of type %. But each time you call y()
you might get a differen element of %.

I guess, you know all this stuff.

Ralf

aldor -laldor -grun domaintest.as
172443481
172443481
1911439442
1127848893

---domaintest.as
#include "aldor"
DomA: with {
x: %;
y: () -> %;
coerce: % -> Integer;
} == add {
Rep == Integer;
import from Rep;
x : % == per random();
y(): % == per random();
coerce(x: %): Integer == rep x;
}
main(): () == {
import from TextWriter, Character, Integer;
a: DomA := x; stdout << (a::Integer) << newline;
b: DomA := x; stdout << (b::Integer) << newline;
a: DomA := y(); stdout << (a::Integer) << newline;
b: DomA := y(); stdout << (b::Integer) << newline;
}
main();
Ralf Hemmecke
2006-02-22 17:04:14 UTC
Permalink
if we were to consider implementation details, then descending to the
foam level would suffice :-)
However, I was really thinking of the abstract model -- no
implementation involved yet.
I think you are more of an expert in this business. I am just a poor
mathematician with some programming knowledge. ;-)
| However, this behaviour is exactly, the difference between a constant
| and a nullary function in Aldor.
The difference is not that between a constant and a nullary function
-- btw, anything defined with "==" is a constant in Aldor :-)
Yes. As I said. "y" is constant "y()" is not.
if your nullary function y evaluates to the *same* value for same
argument each time, then it would do just fine.
I agree, but it does not evaluate to the same thing. And Aldor allows
this. I understand that mathematically a constant and a nullary function
is not much of a difference. I would also conceptually agree if we speak
about functional languages where there are no side effects. But Aldor
allows side-effects.
You won't see any difference.
Except, maybe for the running time if the compiler is not smart enough
to remove
the function call and just replace it with the value.
The real difference in your program is that of *binding time*.
Of course, I agree, that "x" and "y()" can be treated as constants if
"y" where a function in the mathematical sense (returning the same value
for the same input). In that case it is just different "binding time".

But in the example I gave in my previous mail. "y" is not a function
that returns the same value in each invocation. And you don't think that
is a difference?
| Aldor computes the value for x at the time the domain is
| instantiated. So it is constant over the lifetime of the domain
| (unless some dirty tricks change that value). For y it is
| different. That is a function constant. But a constant of type ()->%
| not of type %. Now, of course, if you say "y()", you get something of
| type %. But each time you call y() you might get a differen element of
| %.
|
| I guess, you know all this stuff.
yes, thanks. I'm still puzzled as to why you're collapsing binding time
distinction with constant vs. nullary function.
Maybe, I don't have enough knowledge here. If you could enlighten me,
would be nice...

Ralf
Gabriel Dos Reis
2006-03-03 07:18:50 UTC
Permalink
Ralf Hemmecke <***@hemmecke.de> writes:

[...]

| > | However, this behaviour is exactly, the difference between a constant
| > | and a nullary function in Aldor.
|
| > The difference is not that between a constant and a nullary function
| > -- btw, anything defined with "==" is a constant in Aldor :-)
|
| Yes. As I said. "y" is constant "y()" is not.

yes, however that is because the body is side-effecting, not just
because of "()".

| > if your nullary function y evaluates to the *same* value for same
| > argument each time, then it would do just fine.
|
| I agree, but it does not evaluate to the same thing. And Aldor allows
| this.

yes, however the issue is with the implementation of y(), not because
of the the presence of (). If "literal" was side-effecting you would
get similar trouble.

| I understand that mathematically a constant and a nullary
| function is not much of a difference. I would also conceptually agree
| if we speak about functional languages where there are no side
| effects. But Aldor allows side-effects.

I don't think the issue has to do with having a functional language or
not.
For example, I have been working on a proposal

http://public.research.att.com/~bs/N1521-constant-expressions.pdf

to require C++ compiler to evaluate calls to certain functions with
constant expressions at compile-time, provided their bodies are
"sufficiently simple". Such functions achieve the mapping of
conceptual mathematical functions to computational ones.

| > You won't see any difference.
|
| Except, maybe for the running time if the compiler is not smart enough
| to remove
| the function call and just replace it with the value.

:-)

| > The real difference in your program is that of *binding time*.
|
| Of course, I agree, that "x" and "y()" can be treated as constants if
| "y" where a function in the mathematical sense (returning the same
| value for the same input). In that case it is just different "binding
| time".
|
| But in the example I gave in my previous mail. "y" is not a function
| that returns the same value in each invocation. And you don't think
| that is a difference?

There is a difference, but I do believe the fundamental reason if
becaue of "()".


-- Gaby

Gabriel Dos Reis
2006-02-22 16:48:46 UTC
Permalink
Ralf Hemmecke <***@hemmecke.de> writes:

| Dear Gaby,
|
| On 02/22/2006 04:00 PM, Gabriel Dos Reis wrote:
| > Ralf Hemmecke <***@hemmecke.de> writes:
| > | On 02/22/2006 12:21 AM, Gabriel Dos Reis wrote:
| > | > Ralf Hemmecke <***@hemmecke.de> writes:
| > | > | > | The problem is the "1: %" as a constant (not a nullary
| > | > function).
| > | > | > The distinction is largely syntactic, not fundamental.
| > | > | | I was once told that in Aldor the difference between
| > | > | a: %
| > | > | and
| > | > | b: () -> %
| > | > | is that
| > | > | b() will run a program which might side-effect other things or even
| > | > | return something different each time.
| > | > expanding on my preivous answer, have a look at the section 5.2 os
| > | > the
| > | > Aldor user guide on literal forming -- you can define your own function
| > | > to interpret a string literal as a constant.
| > | | I knew about this Literal stuff before...
| > I have no doubt about that :-)
| > |
| > http://lists.gnu.org/archive/html/axiom-developer/2006-02/msg00154.html
| > | | But as you see, if you write a domain that has a function
| > | string: Literal -> %,
| > | it is a function and that means that "1" and "1" need not give
| > | identical values.
| > yes, that is precisely why I said in an earlier message that the
| > distinction is largely syntactic. it is not something fundamental in
| > the context of your discussion about axiom and o stuff.
| > Underneath, everything is a function in Aldor!
|
| Well, it might depend on which level you look at it. If the generated
| C code is concerned, I have no idea about that.

if we were to consider implementation details, then descending to the
foam level would suffice :-)

However, I was really thinking of the abstract model -- no
implementation involved yet.

| But if it were really just syntactic, then the output given below is
| strange.
|
| However, this behaviour is exactly, the difference between a constant
| and a nullary function in Aldor.

The difference is not that between a constant and a nullary function
-- btw, anything defined with "==" is a constant in Aldor :-)

if your nullary function y evaluates to the *same* value for same
argument each time, then it would do just fine. You won't see any
difference. The real difference in your program is that of *binding
time*.

| Aldor computes the value for x at the time the domain is
| instantiated. So it is constant over the lifetime of the domain
| (unless some dirty tricks change that value). For y it is
| different. That is a function constant. But a constant of type ()->%
| not of type %. Now, of course, if you say "y()", you get something of
| type %. But each time you call y() you might get a differen element of
| %.
|
| I guess, you know all this stuff.

yes, thanks. I'm still puzzled as to why you're collapsing binding time
distinction with constant vs. nullary function.

-- gaby
Gabriel Dos Reis
2006-02-22 15:00:44 UTC
Permalink
Ralf Hemmecke <***@hemmecke.de> writes:

| On 02/22/2006 12:21 AM, Gabriel Dos Reis wrote:
| > Ralf Hemmecke <***@hemmecke.de> writes:
| > | > | The problem is the "1: %" as a constant (not a nullary
| > function).
| > | > The distinction is largely syntactic, not fundamental.
| > | | I was once told that in Aldor the difference between
| > | a: %
| > | and
| > | b: () -> %
| > | is that
| > | b() will run a program which might side-effect other things or even
| > | return something different each time.
| > expanding on my preivous answer, have a look at the section 5.2 os
| > the
| > Aldor user guide on literal forming -- you can define your own function
| > to interpret a string literal as a constant.
|
| I knew about this Literal stuff before...

I have no doubt about that :-)

| http://lists.gnu.org/archive/html/axiom-developer/2006-02/msg00154.html
|
| But as you see, if you write a domain that has a function
| string: Literal -> %,
| it is a function and that means that "1" and "1" need not give
| identical values.

yes, that is precisely why I said in an earlier message that the
distinction is largely syntactic. it is not something fundamental in
the context of your discussion about axiom and o stuff.
Underneath, everything is a function in Aldor!


-- Gaby
Ralf Hemmecke
2006-02-21 11:21:39 UTC
Permalink
Post by Bill Page
map(f:R -> S)(p:RX):SX == {...
map(f:R -> S):RX->SX ==
(p:RX):SX +-> { ...
Is this equivalent?
Yes.

And to make it even clearer...

In Aldor "==" defines a constant. And the constant here is "map". So it
should actually be written as

map: (R -> S) -> RX -> SX == {
(f: R -> S): (RX -> SX) +-> { (p: RX): SX +-> {...} }
}

We all know that functions are first class citizens.

http://www.aldor.org/docs/HTML/chap6.html#5

You probably agree that it is somehow a good thing that the Aldor
compiler adds a bit of syntactic sugar for such constructions.

Ralf
Bill Page
2006-02-20 20:01:13 UTC
Permalink
Post by Ralf Hemmecke
Post by Bill Page
Post by Ralf Hemmecke
Post by Francois Maltey
1/ Can I (or cannot) remain Expressions as
x+1/(y+1)
y+1/(x+1)
and do not have a single denominator.
Unfortunately, I have no idea, how to do this. :-(
It is obvious, isn't it, that to do this is Axiom you *must*
find a domain of which this expression can be a member?
Of course, you are right. I was just saying that I don't know of
a domain which behaves as one would expect. So the next thing I
would do is to write another domain which behaves (and inherits)
most things from Expression Integer but does not group expressions
together so that they are over one denominator.
Yes, that is a good idea if you desire to solve the general
problem of defining a domain in which contains all possible
expressions as members. Perhaps this is the kind of "userdomain"
that Jenks and Trager had in mind in the design of BNatural.

http://wiki.axiom-developer.org/BNatural

How would this differ from Aldor's ExpressionTree domain?
Post by Ralf Hemmecke
...
Post by Bill Page
Post by Ralf Hemmecke
But, I'd like to warn you. Don't follow Bill's suggestion.
I think it is strange how confident both of us are in the
opposite opinion. :)
I don't think you have shown any flaw in my suggestion. It seems
to me to be very reasonable solution to the problem originally
posed by Francois. In fact this same approach is used on other
parts of Axiom.
x+1/(y+1) + y+1/(x+1)
since
(x+1/(y+1) + y+1/(x+1))$DMP([x,y],EXPR INT)
shows as
y + x + 2
(4) x + y + ----------------
(x + 1)y + x + 1
Type: DistributedMultivariatePolynomial([x,y],Expression Integer)
You are right that this might quite not produce the type of trigonometric
expansion that Francois has in mind. On the other hand, the result
is still well defined in the sense that the parts of the expression
that are representable as a distributed polynomial remain and
everything else is in the coefficient domain. I think it would be
better than what Axiom currently produces for:

expand sin((x+1/(y+1) + y+1/(x+1)))
Post by Ralf Hemmecke
Of course, ad hoc solutions are not bad as long as one knows
what one is doing, but I somehow don't like the ad hoc method.
I don't think this solution should be classed as "ad hoc". It
seems to me to be consistent with other operations of this
kind already done by Axiom. But I do agree that it is not a
fully general solution.
Post by Ralf Hemmecke
Either there is a clever program that guesses correctly what
the user wants, or, if this is not possible, the user should
think a bit more and perhaps add more knowledge to the system.
Otherwise Axiom ends up in being like all the other untyped CAS.
I agree.
Post by Ralf Hemmecke
... I hope you agree that if Axiom is not able to do the things
that Francois wants in a clear way, then it would be better
(at least for the future) to add a nice feature to the system
instead of being satisfied that the wish can be fulfilled by an
ad-hoc-misuse of existing domains.
I agree (except I do not class my proposed solution as an
ad-hoc-misuse :).
Post by Ralf Hemmecke
Post by Bill Page
In particular it is important to realize
that the object that is called a DMP in Axiom is almost, but
not quite that same thing as what a mathematician would call a
polynomial. It is actually something a little more general. It
makes a explicit distinction between the underlying coefficient
domain and the polynomial domain itself. This is something that
one would not (normally) do in mathematics.
Well, a polynomial in n variables with coefficients in a ring R is
an element of
\Oplus_{e \in N^n} R
where N is the non-negative integers.
If you like, you can attach variable names somewhere. Yes, I
also know that some people define polynomials differently.
This is good enough for me and apparently to the designers of DMP.
They do attach the polynomial variables names, but on the other hand
they also provide the 'vectorize' operator.
Post by Ralf Hemmecke
...
Post by Bill Page
(24) x + x
DistributedMultivariatePolynomial([x,y],Expression Integer)
So, let me interpret a polynomial as above as a function (with
finite support) from the domain of exponents to the domain of
coefficients.
(24) clearly has support { [1,0], [0,0] } an is therefore by no
means equal to the polynomial 2x which has support { [1,0] }.
Ok.
Post by Ralf Hemmecke
I am not really saying that Axiom is doing something wrong, I am
just warning that the use of DMP([x,y], Expression Integer) can
be misleading for people that don't know how Axiom works internally.
To write your interpretation above you did not need to know how
Axiom works internally. If people where equipped with your explanation
I don't think the result would be misleading. This is the type of
documentation that I think we need to have for Axiom's library.
Post by Ralf Hemmecke
Those people would probably treat (24) as 2x and that interpretation
would be wrong.
It is only wrong in the context of DMP([x,y], Expression Integer).
In domain 'Expression Integer' it is correct. That is why I say
that Axiom demands that one first state clearly the domain and
only then consider the expression.
Post by Ralf Hemmecke
Post by Bill Page
Post by Ralf Hemmecke
1
(5) - x
x
DistributedMultivariatePolynomial([x,y],Expression Integer)
...
I think this is only confusing if you try to think of this
expression out of context, that is, without thinking about the
structure of the domain to which is belongs.
The context is clearly given. It's the type of (5). Right, I
could even predict, that Axiom should give back that expression.
(How could I otherwise have constructed it?) But the two x's one
sees, have different origins and are therefore not equal.
It is only in the context of this domain that they are not equal.
If I coerce this result to the domain 'Expression Integer' they
will be treated as equal.
Post by Ralf Hemmecke
By the way, you can achieve similar confusing things with Maple.
f:=proc() local x; x end;
evalb(a=b);
That behaviour had once cost me several days to trace down a bug.
Clearly, a looks like x and b looks like x. But they are not equal.
I haven't found this to be documented.
In Maple terminology this is known as an "escaped local variable".
I think this situation is completely different than in Axiom. It is
reasonable to conclude that this odd behaviour in Maple occurs
because Maple does not have any concept of domain, so it cannot
(at least not easily) specify a situation (domain) in which the
equality 'a=b' can be properly evaluated. Notice that in Axiom
'=' is also an operator and we need to know the domain which
provides this operation.
Post by Ralf Hemmecke
...
Regards,
Bill Page.
Ralf Hemmecke
2006-02-21 09:54:03 UTC
Permalink
Hello Bill,
Post by Bill Page
Yes, that is a good idea if you desire to solve the general
problem of defining a domain in which contains all possible
expressions as members. Perhaps this is the kind of "userdomain"
that Jenks and Trager had in mind in the design of BNatural.
http://wiki.axiom-developer.org/BNatural
How would this differ from Aldor's ExpressionTree domain?
Ehm...

If I were to program BNatural, I would certainly consider to take
ExpressionTree from libalgebra. Well that domain is not yet rich enough,
but it is in some way an approach to forget about types. In libalgebra
most domains are of type ExpressionType and Parsable.

define ExpressionType: Category == Join(OutputType, PrimitiveType) with {
extree: % -> ExpressionTree;
...
}

define Parsable: Category == InputType with {
eval: TREE -> Partial %;
eval: LEAF -> Partial %;
eval: (MachineInteger, List TREE) -> Partial %;
}

where TREE==>ExpressionTree, LEAF==>ExpressionTreeLeaf.

So one basically has a coercion from and to ExpressionTree.

But I am not so sure whether one should extend ExpressionTree properly
with any operation you could imagine or rather use some syntax parsing
code of the Aldor compiler itself. Look at the output of
aldor -fasy foo.as
for some arbitrary program foo.as. One basically has to extract
"mathematical" expressions and do something reasonable with them. Yes,
maybe wrap them with something like ExpressionTree.

To be honest, I haven't really thought about that, because I am lacking
some expertise here.

Ralf
Ralf Hemmecke
2006-02-21 09:59:09 UTC
Permalink
Hello Bill,
Post by Bill Page
This is good enough for me and apparently to the designers of DMP.
They do attach the polynomial variables names, but on the other hand
they also provide the 'vectorize' operator.
I haven't found "vectorize". Which function do you mean?

Ralf
Ralf Hemmecke
2006-02-21 11:08:42 UTC
Permalink
Hello Bill,

This is about the "x + x" output...
Post by Bill Page
Post by Ralf Hemmecke
I am not really saying that Axiom is doing something wrong, I am
just warning that the use of DMP([x,y], Expression Integer) can
be misleading for people that don't know how Axiom works internally.
To write your interpretation above you did not need to know how
Axiom works internally. If people where equipped with your explanation
I don't think the result would be misleading. This is the type of
documentation that I think we need to have for Axiom's library.
See
http://wiki.axiom-developer.org/DistributedMultivariatePolynomial
;-)

Ralf
Bill Page
2006-02-20 20:16:14 UTC
Permalink
Post by Ralf Hemmecke
P := DistributedMultivariatePolynomial([x,y],Expression Integer)
b := monomial(x,[0,0]::DirectProduct(2,NNI))$P
...
I wrote that it could *lead* to "surprising" results. I.e.,
I could imagine that some innocent looking computation would
not be correct in the situation above. For example,
differentiate(b+x,x)
gives one, but
gives two.
(1) -> P := DistributedMultivariatePolynomial([x,y],Expression Integer)

(1) DistributedMultivariatePolynomial([x,y],Expression Integer)
Type: Domain

(2) -> b := monomial(x,[0,0]::DirectProduct(2,NNI))$P

(2) x
Type: DistributedMultivariatePolynomial([x,y],Expression Integer)

(3) -> differentiate(b+x,x)

(3) 1
Type: DistributedMultivariatePolynomial([x,y],Expression Integer)

(4) -> differentiate(b+x,x)@EXPR INT

(4) 2
Type: Expression Integer
Note that I did not even need to ask to coerce b+x to EXPR INT...
Of course, as we are discussing this now, this does not come as
a surprise. But I bet that even for quite an experienced axiom
user, who did not follow this thread for some reason, it will be
difficult to spot the mistake. Especially if he doesn't realize
that she wanted to compute something else...
I would call the result in (3) a bug. It seems to me that perhaps
'differentiate$DMP' is making a unwarranted assumption that the
coefficients of DMP are constant. I cannot imagine a properp
mathematical definition of 'differentiate' that depended on the
distinction of polynomial coefficients versus variables.
Part of the reason for the confusion, I think, is because the
common OutputForm for polynomials does not typographically
identify polynomial variables versus coefficients. But if, say
the polynomial variables were always printed in bold face roman
type but the coefficients were printed in italic, it might be
more clear what is going on.
I think that this is a very nice idee. I guess this could be
even realized on text terminals, couldn't it?
To do this in LaTeX output is obviously quite straight forward.
To do it on text terminals I think would require support of
'curses' or a similar library. I am not sure that Axiom text
output (really a function of the underlying lisp - GCL, I guess)
supports 'curses'. Do you think suport for these conventions in
text output are really that important?

Regards,
Bill Page.
Bill Page
2006-02-21 14:36:44 UTC
Permalink
Ralf,
...
See
http://wiki.axiom-developer.org/DistributedMultivariatePolynomial
;-)
Thanks! I think your description is excellent.

Regards,
Bill Page.
Ralf Hemmecke
2006-02-21 15:13:01 UTC
Permalink
Post by Ralf Hemmecke
differentiate(p: %,v: OV) ==
multivariate(differentiate(univariate(p,v)),v)
where univariate just converts p to an element of
SparseUnivariatePolynomial(%). (BTW, that's already a trick!)
Alternatively, if we are going to allow constructions in which
the coefficient domain of SUP might contain the polynomial
variable, then the implementation of 'differentiate' in SUP
should be corrected.
Look more closely. SUP does not even know of a variable name. So how
should it do something else than differentiate with respect to the only
(unamed) variable it has? It's a univariate polynomial in the sense of
being a function with finite support from the natural numbers to the
coefficient ring.

Ralf
Bill Page
2006-02-21 14:59:44 UTC
Permalink
On February 21, 2006 4:26 AM Ralf Hemmecke
Post by Ralf Hemmecke
Post by Bill Page
Post by Francois Maltey
...
P := DMP([x,y], EXPR INT)
a :P := x
b := a/x
differentiate(b,x) -- 1/x
(4) -> differentiate(b,x)
1
(4) -
x
Type: DistributedMultivariatePolynomial([x,y],Expression Integer)
I think this result should be classed a bug. The 'differentiate'
operation apparently makes some incorrect assumptions about the
(5) -> differentiate(b::EXPR INT,x)::P
(5) 0
Type: DistributedMultivariatePolynomial([x,y],Expression Integer)
Well, Bill, imagine you had to programm
DistributedMultivariatePolynomial.
In gdpoly.spad we see
differentiate(p: %,v: OV) ==
multivariate(differentiate(univariate(p,v)),v)
where univariate just converts p to an element of
SparseUnivariatePolynomial(%). (BTW, that's already a trick!)
However, it seems the most obvious thing to do.
Now you suggest to do that differently, since the
coefficients of that univariate polynomial might also
contain the variable x.
I haven't looked any more deeply in the source code than this
but if it was already well documented that SUP requires that no
variables occur in the coefficient domian, then I think I would
prefer that the conversion to SUP take account of the fact that
the polynomial coefficients might contain variables in the same
way that the coercion to EXPR INT in the example (5) above does.

Alternatively, if we are going to allow constructions in which
the coefficient domain of SUP might contain the polynomial
variable, then the implementation of 'differentiate' in SUP
should be corrected.
Post by Ralf Hemmecke
Well, would be possible, but obviously the designer of DMP
(or rather GDMP) did not think of such a strange thing like
having the same variable as the indeterminate of the polynomial
and at the same time in the domain of coefficients.
I agree that the usage is obscure but it still seems to me to
be an error in the implementation of either 'univariate' in the
code you quoted above or 'differentiate' in SUP.
Post by Ralf Hemmecke
Still, it's a bug, because that behaviour should at least be
very vell documented. It is, however, not so clear where to do
this. I suggest there should be a note in DMP rather than the
category PartialDifferentialRing (where the signature comes from).
I agree.

Regards,
Bill Page.
Bill Page
2006-02-21 13:36:01 UTC
Permalink
Post by Doug Stewart
<snip>
Wow!!! I have been watching and learning Axiom for the last
two months, and this thread has really help me.
I am glad that this dialogue was helpful to you. :)
Post by Doug Stewart
What I have found is that I can pick up Axiom in a simple way
quite quickly but then I hit a wall that I could not seem to
get past.
I think your experience is common among new users of Axiom.
Post by Doug Stewart
This thread has brought to light what the wall is and has
help me muchly.
What is this "wall"? Could you explain it in your own words?
Post by Doug Stewart
Could someone in the know take some material from this thread
and use it in the manual?
This comment deserves the reaction that you will find in
almost all open source projects: *You* are now the person
"in the know" about what potential Axiom users like you don't
know. So *you* are the best person to extract and reformat
the material from this thread that *you* think would be of
some benefit to new users.

The people who are working up close with the internals of
Axiom often do not appreciate what it is that the new people
don't understand. As a result, the documentation that they
might find time to write is often focused on the wrong issues.
And very often these people are not particularly good at writing
technical prose. Usually these people will interpret suggestions
such as yours in a rather negative manner: You are suggesting
even more work for them and they are already very busy!

And ... we have this wonder tool called a "wiki" that allows
everyone - anyone anywhere in the world - to contribute new
documentation and to update web pages online, in real time.
The hope is that sooner or later the seeds of email exchanges
such as these will fall on some intellectually fertile and
motivated individual who is willing to contribute to the Axiom
project by writing documentation, users' guides and tutorials.
A lot of the content already on the Axiom Wiki

http://wiki.axiom-developer.org

originated for such emails.

The Axiom Wiki makes it possible for almost anyone to create
documentation. It is easy to create a new page, edit the
contents of exiting pages, give online examples of Axiom
calculations, and even directly edit over-the-web, the contents
of the Axiom source distribution which are written as literate
programming documents.

Almost all open source projects are starving for people with
writing talents and or even people who may not be such good
writers but who do have sufficient motivation to at least make
some kind of contribution. Of the potentially millions of people
around the world who might eventually visit the open source
project web site, there is always the hope that a few of these
people might step forward to help.
Post by Doug Stewart
I know that just reading this has opened my eyes.
Reading and replying to email in a long and detailed dialogue
is one thing (quite easy really), but writing good documentation
is another. In fact, in the three year history of the Axiom
open source project we have generated a huge searchable on-line
resource of this sort of dialogue in the axiom-developer archive:

http://mail.nongnu.org/archive/html/axiom-developer

It is just waiting to be mined by someone devoted to the task
of making more and better documentation available to other Axiom
users.

The open source movement has been called a "gift culture", i.e.
one where one's social standing is at least in part determined
by what one offers freely to others. This is in contrast to
some other forms of cooperation between individuals such as
embodied in commercial proprietary software, where one expects
to get paid for a product or for services rendered.

I think one gift that a lot of us working on Axiom would hope
to receive some day is the contributions of new people who are
willing and able to work on the Axiom documentation.

Regards,
Bill Page.
Bill Page
2006-02-21 17:01:21 UTC
Permalink
Ralf,
Post by Ralf Hemmecke
Post by Ralf Hemmecke
differentiate(p: %,v: OV) ==
multivariate(differentiate(univariate(p,v)),v)
where univariate just converts p to an element of
SparseUnivariatePolynomial(%). (BTW, that's already a trick!)
Alternatively, if we are going to allow constructions in which
the coefficient domain of SUP might contain the polynomial
variable, then the implementation of 'differentiate' in SUP
should be corrected.
Look more closely. SUP does not even know of a variable name.
So how should it do something else than differentiate with respect
to the only (unamed) variable it has? It's a univariate polynomial
in the sense of being a function with finite support from the
natural numbers to the coefficient ring.
I am looking at:

http://wiki.axiom-developer.org/axiom--test--1/src/algebra/PolySpad

and

http://wiki.axiom-developer.org/axiom--test--1/src/algebra/PolycatSpad

but I am confused by this result:

(1) -> S:=SUP EXPR INT

(1) SparseUnivariatePolynomial Expression Integer
Type: Domain

(2) -> ex1:=(x^2+1)$S

2
(2) x + 1
Type: SparseUnivariatePolynomial Expression Integer

(3) -> differentiate(ex1)$S

(3) 0
Type: SparseUnivariatePolynomial Expression Integer

Ok, so 'differentiate$SUP' treated 'x^2+1' as being in the
coefficient domain, right? But:

(4) -> differentiate(ex1,x)$S

(4) 2x
Type: SparseUnivariatePolynomial Expression Integer

')set message bottomup on' shows that 'differentiate' with
signature '(SUP EXPR INT,SYMBOL) -> SUP EXPR INT' is called
from SUP.

(4) -> differentiate(ex1,x)$S

Function Selection for differentiate
Arguments: (SUP EXPR INT,VARIABLE x)
Target type: SUP EXPR INT
From: SUP EXPR INT
-> no appropriate x found in Expression Integer
-> no appropriate x found in Integer
-> no appropriate x found in Expression Integer
-> no appropriate x found in Integer

[1] signature: (SUP EXPR INT,SYMBOL) -> SUP EXPR INT
implemented: slot $$(Symbol) from SUP EXPR INT

This function seems to come from 'DifferentialExtension' in

http://wiki.axiom-developer.org/axiom--test--1/src/algebra/CatdefSpad

and this seems correct to me. So I am confused as to why
'differentiate(univariate(p,v))' does not seem to yield this
same result. Can you help?

It seems to me that the interrelationship between all of these
polynomial categories, domains and packages is remarkably
convoluted. I am not saying necessarily that it does not have
to be this complicated, but certainly we would all benefit
greatly if this could be clearly and completely documented.

Regards,
Bill Page
Ralf Hemmecke
2006-02-21 21:53:02 UTC
Permalink
Post by Bill Page
(4) -> differentiate(ex1,x)$S
This function seems to come from 'DifferentialExtension'
No. I rather think it comes from 'PartialDifferentialRing(Symbol)'.
Look at Hyperdoc. Browse SUP and view Operations->Origins (Filter
"differentiate").
Post by Bill Page
So I am confused as to why
'differentiate(univariate(p,v))' does not seem to yield this
same result. Can you help?
Not really. I think there is a bug here, since x is sometimes treated as
the indeterminate of SUP and sometimes not.
Post by Bill Page
It seems to me that the interrelationship between all of these
polynomial categories, domains and packages is remarkably
convoluted.
I don't really think so. The problematic thing is to take
"Expression Integer" as an argument in the construction of SUP.

Could you explain in which sense SUP(Expression Integer) should be
semantically different from Expression(Integer)?

Isn't an element of SUP(Expression Integer) also an expression?
It is obvious that Axiom can construct SUP(Expression Integer), but does
this make sense?

I do not fully understand the "Expression" constructor, but I somehow
consider it as a domain that contains every expression. Therefore, I
think constructing higher domains that are built on Expression should
not yield a bigger class than Expression itself.

What would be the relation between
SUP(Expression Integer) and Expression(Integer) on a semantic level?
Equality, subset, superset?

Ralf
William Sit
2006-02-21 14:30:01 UTC
Permalink
Post by Francois Maltey
Hello,
Thanks for previous help,
now I can compile a package and add spy-print inside !
1/ Can I (or cannot) remain Expressions as
x+1/(y+1)
y+1/(x+1)
and do not have a single denominator.
Please see SandBoxPartialFraction.

William
Bill Page
2006-02-21 17:21:53 UTC
Permalink
Post by Bill Page
Post by Ralf Hemmecke
differentiate(p: %,v: OV) ==
multivariate(differentiate(univariate(p,v)),v)
...
http://wiki.axiom-developer.org/axiom--test--1/src/algebra/PolySpad
and
http://wiki.axiom-developer.org/axiom--test--1/src/algebra/PolycatSpad
(1) -> S:=SUP EXPR INT
(1) SparseUnivariatePolynomial Expression Integer
Type: Domain
(2) -> ex1:=(x^2+1)$S
2
(2) x + 1
Type: SparseUnivariatePolynomial Expression Integer
(3) -> differentiate(ex1)$S
(3) 0
Type: SparseUnivariatePolynomial Expression Integer
Ok, so 'differentiate$SUP' treated 'x^2+1' as being in the
(4) -> differentiate(ex1,x)$S
(4) 2x
Type: SparseUnivariatePolynomial Expression Integer
')set message bottomup on' shows that 'differentiate' with
signature '(SUP EXPR INT,SYMBOL) -> SUP EXPR INT' is called
from SUP.
(4) -> differentiate(ex1,x)$S
Function Selection for differentiate
Arguments: (SUP EXPR INT,VARIABLE x)
Target type: SUP EXPR INT
From: SUP EXPR INT
-> no appropriate x found in Expression Integer
-> no appropriate x found in Integer
-> no appropriate x found in Expression Integer
-> no appropriate x found in Integer
[1] signature: (SUP EXPR INT,SYMBOL) -> SUP EXPR INT
implemented: slot $$(Symbol) from SUP EXPR INT
This function seems to come from 'DifferentialExtension' in
http://wiki.axiom-developer.org/axiom--test--1/src/algebra/CatdefSpad
and this seems correct to me. So I am confused as to why
'differentiate(univariate(p,v))' does not seem to yield this
same result. Can you help?
Oh! Re-reading this I just noticed something.

Shouldn't this differentiation be written
'differentiate(univariate(p,v),v)' in SUP:

differentiate(p: %,v: OV) ==
multivariate(differentiate(univariate(p,v),v),v)

-------

That should allow the differentiation of any expressions occuring
in the underlying Ring.

Regards,
Bill Page.
Bill Page
2006-02-21 14:35:12 UTC
Permalink
Post by Ralf Hemmecke
Post by Bill Page
This is good enough for me and apparently to the designers of DMP.
They do attach the polynomial variables names, but on the other hand
they also provide the 'vectorize' operator.
I haven't found "vectorize". Which function do you mean?
I am sorry. I should have written 'vectorise'. See within:

http://wiki.axiom-developer.org/axiom--test--1/src/algebra/PolycatSpad

Regards,
Bill Page
Bill Page
2006-02-21 23:41:37 UTC
Permalink
Post by Ralf Hemmecke
...
Post by Bill Page
(4) -> differentiate(ex1,x)$S
This function seems to come from 'DifferentialExtension'
No. I rather think it comes from 'PartialDifferentialRing(Symbol)'.
Look at Hyperdoc. Browse SUP and view Operations->Origins (Filter
"differentiate").
I think Hyperdoc is confused.
Francois Maltey
2006-02-22 18:11:12 UTC
Permalink
Could you please define in what sense "Otherwise we don't
get a polynomial, obviously."? To me this is not obvious -
it is wrong.
Why should this be wrong?
In mathematics, a polynomial is an expression in which constants
and variables are combined using (only) addition, subtraction,
and multiplication. Thus, 7x^2+4x-5 is a polynomial; 2/x is not.
I have the same point of view than Martin,
everything is done in DMP in order to have a polynomial ring,
DMP isn't only a << collect >> command which factorise x and so.
I think this definition is less general it needs to be and
difficult to apply in the context of Axiom.
If we change DMP assumption, it's no more ring.
We need to know what are "constants" and what are "variables"
So the same variable is forbiden in the constant ring.
I find it's a bug to allow DMP ([X,Z], DMP ([X,Y], INT))
I recall that in the Algebra course I attended, the polynomial
ring was defined as a ring (of coefficients) together with a
variable which is to be transcendent over that ring.
That definition is much better. In the case we are discusing
the ring of coefficients is the domain 'EXPR INT' which
includes expressions of the form '1/x' and so it is correct
to say that '2/x' is not in itself a polynomial but it can
be a coefficient in a polynomial.
I don't think so,
a polynomial ring has variables which are not in the initial ring.
The DMP error (for derivative) isn't in the derivative function but
in the fact that axiom accepts 1/x has variable in DMP[x].

And 1/x isn't transcendent over that rign because y=1/x is solution of
xy-1=0 in this field.

Either we say to the user he _must_ be carreful with this,
(only in the EXPR INTEGER field?)
Either monomial command of DMP reject 1/x coefficient if x is a variable.

In France we say we can be << jesuite >> :
The real axiom accepts coefficients as 1/x in DMP ([x], EXPR INT)
because axiom EXPR INT isn't perfect, but it souldn't.
But I'm sure it's a mistake to change derivative.
How would you use such a domain to solve the problem originally
posed by Francois about expansion of trigonometric expressions
that started this thread?
When we expand a trigonometric expression,
the question is a << linear one >> not a polynomial one.

We expand more often sin (4*x+5*y) than sin (x^2+x) ;
for sin (x^2+x) we use series.

Have a good day !

Francois
Martin Rubey
2006-02-22 13:54:55 UTC
Permalink
Post by Bill Page
Martin,
Post by Martin Rubey
I'm currently out of time. But I'm a little afraid of the
direction the discussion takes currently.
I on the other hand am very happy that this discussion
seems to accurately reflect the concept of type in Axiom.
well, I'd be happier if I could defend my point of view. Just, I can't,
currently. Still I'll try to (partially) respond to this message... Please bear
with me.
Post by Bill Page
Post by Martin Rubey
I believe that the intension of a constructor like DMP is to cover
*polynomials*.
I agree. "cover" is the operative word. This does not preclude that the type
DMP in Axiom might be a little more general than what is called a polynomial
in some mathematical uses (but perhaps not others).
Post by Martin Rubey
If we allow (2*x+1/x)::DMP([x], EXPR INT), i.e., allowing 1/x as a
coefficient, then it must be clear that the "x" in 1/x is something
different than the "x" in 2*x. Otherwise we don't get a polynomial,
obviously.
I think this is wrong. In fact, it is clear from the implementation of Axiom
that whether the 'x' in these two cases is the same or not depends on which
domain to which they belong.
Could you please define in what sense "Otherwise we don't get a polynomial,
obviously."? To me this is not obvious - it is wrong.
Why should this be wrong?

Here's a definition for polynomial from wikipedia:

In mathematics, a polynomial is an expression in which constants and
variables are combined using (only) addition, subtraction, and
multiplication. Thus, 7x^2+4x-5 is a polynomial; 2/x is not.

I recall that in the Algebra course I attended, the polynomial ring was defined
as a ring (of coefficients) together with a variable which is to be
transcendent over that ring.

I guess you know that, so there is probably a misunderstanding somewhere. Just
to be clear:

sin x + y*cos x + y^2* tan x

is perfectly allright a polynomial in y.
Post by Bill Page
Documentation is a good thing. But why should we retain behaviour in Axiom
that is mathematically incorrect? What advantage does this odd behaviour of
'differentiate' have over a mathematically correct implementation?
I think that 'differentiate' does not exhibit odd behaviour. Why do you think
it's odd?

Of course, if you claim that x+1/sin(x) is a polynomial, than I'm out of luck.

You said, given
Post by Bill Page
Post by Martin Rubey
Post by Bill Page
Post by Francois Maltey
P := DMP([x,y], EXPR INT)
a :P := x
b := a/x
differentiate(b,x) -- 1/x
(4) -> differentiate(b,x)
1
(4) -
x
Type: DistributedMultivariatePolynomial([x,y],Expression Integer)
On the other hand a 'differentiate' operator that returns 1/x in (4) above
would violate the mathematical definition of derivative, so I think it cannot
possibly be right.
I wouldn't say that this violates the "mathematical definition of
derivative". The derivative of a univariate polynomial is defined by sending
x^n to n*x^(n-1) and linear extension. There is no such thing as 1/x in the
polynomial world. If you want a domain that contains x and 1/x, consider using
Laurent polynomials. In fact I cannot see a single reason to consider a domain
DMP(vars, EXPR INT) at all, except for the fact that we do not have a domain
EXPR(vars, coefficients) yet.
Post by Bill Page
Post by Martin Rubey
Note that b::UP([x], INT) or b::POLY INT give errors!
Obviouse 'b' has no representation in these domains.
Yes it has: 1 is a UP([x], INT).

Martin
William Sit
2006-02-24 13:06:54 UTC
Permalink
Post by Martin Rubey
If we allow (2*x+1/x)::DMP([x], EXPR INT), i.e., allowing 1/x as a
coefficient, then it must be clear that the "x" in 1/x is something
different than the "x" in 2*x. Otherwise we don't get a polynomial,
obviously.
Martin,
Post by Bill Page
I think this is wrong. In fact, it is clear from the implementation of Axiom
that whether the 'x' in these two cases is the same or not depends on which
domain to which they belong.
Any scientific literate person, when (s)he wrote down:

2*x + 1/x

would mean that there is only ONE x, the x means the same thing throughout the
expression. So

(1) -> (2*x+1/x)::DMP([x], EXPR INT)

2
2x + 1
(1) -------
x
Type: DistributedMultivariatePolynomial([x],Expression Integer)
(2) -> degree(%)

(6) [0]

is perfectly correctly interpreted by Axiom. The entire expression is a
coefficient, in EXPR INT. If you )set mess bot on, you'll see that Axiom
actually computes all this in FRAC POLY INT!

However, I think Axiom is wrong in allowing that, since x, being an
indeterminate over EXPR INT, should not be in EXPR INT. The coercion should
simply fail, or end up in FRAC DMP([x], EXPR INT).

Note that even if the following is used, Axiom continues to "retract" the x from
1/x to EXPR INT. This is simply wrong.

x:DMP([x], EXPR INT):=x
2*x + 1/x
degree(%)
[1]

On the other hand, the following is correct, and should be the case no matter
what the coefficient domain is.

y:DMP([y], INT):=y
2*y+1/y

2
2y + 1
-------
y
Type: Fraction DistributedMultivariatePolynomial([y],Integer)

The two cases should not be handled differently.

If a user wants to push the result down to the coefficient domain, it should be
done with a substitution map, explicitly, and the user should not use x in EXPR
INT.

William
Bill Page
2006-02-22 17:13:36 UTC
Permalink
Martin,
...
Please bear with me.
No problem. Respond as and when you get time... :)
Post by Bill Page
Post by Martin Rubey
If we allow (2*x+1/x)::DMP([x], EXPR INT), i.e., allowing 1/x
as a coefficient, then it must be clear that the "x" in 1/x
is something different than the "x" in 2*x. Otherwise we don't
get a polynomial, obviously.
I think this is wrong. In fact, it is clear from the
implementation of Axiom that whether the 'x' in these two
cases is the same or not depends on which domain to which
they belong.
Perhaps I should have said this differently. Yes, I do agree that
the 'x' in '1/x' and '2*x' are different. But they are not
different in the sense in which 'x' and 'y' are different, i.e.
they are not different variables - they are the same variable
used in two different ways. In particular the 'x' in '1/x' is
a member of the coefficient domain just like '2', while the 'x'
in '2*x' is a member of the polynomial domain. Furthermore the
symbol '*' denotes an operation defined in the polynomial
domain, while the symbol '/' denotes an operation in the
coefficient domain.
Post by Bill Page
Could you please define in what sense "Otherwise we don't
get a polynomial, obviously."? To me this is not obvious -
it is wrong.
Why should this be wrong?
In mathematics, a polynomial is an expression in which constants
and variables are combined using (only) addition, subtraction,
and multiplication. Thus, 7x^2+4x-5 is a polynomial; 2/x is not.
I think this definition is less general it needs to be and
difficult to apply in the context of Axiom. We need to know
what are "constants" and what are "variables" and where
"addition", "subtraction" and "multiplication" are defined.
I recall that in the Algebra course I attended, the polynomial
ring was defined as a ring (of coefficients) together with a
variable which is to be transcendent over that ring.
That definition is much better. In the case we are discusing
the ring of coefficients is the domain 'EXPR INT' which
includes expressions of the form '1/x' and so it is correct
to say that '2/x' is not in itself a polynomial but it can
be a coefficient in a polynomial. And if the degree of the
term in which such a coefficient appears is 0, then by
convention we will write this polynomial in a way that looks
the same as '2/x'.
I guess you know that, so there is probably a misunderstanding
sin x + y*cos x + y^2* tan x
is perfectly allright a polynomial in y.
I agree, but it is also a perfectly good polynomial in x
provided that it can appear as a member of the coefficient
domain:

(1) -> (sin x + y*cos x + y^2* tan x)$UP(x,EXPR INT)

2
(1) y tan(x) + sin(x) + y cos(x)
Type: UnivariatePolynomial(x,Expression Integer)

(2) -> degree %

(2) 0
Type: NonNegativeInteger
Post by Bill Page
Documentation is a good thing. But why should we retain
behaviour in Axiom
Post by Bill Page
that is mathematically incorrect? What advantage does this
odd behaviour of
Post by Bill Page
'differentiate' have over a mathematically correct implementation?
I think that 'differentiate' does not exhibit odd behaviour.
Why do you think it's odd?
Of course, if you claim that x+1/sin(x) is a polynomial, than
I'm out of luck.
Indeed, I think you are out of luck. :(

(3) -> ex1:=(x+1/sin(x))$UP(x,EXPR INT)

1
(3) x + ------
sin(x)
Type: UnivariatePolynomial(x,Expression Integer)

(4) -> degree ex1

(4) 1
Type: PositiveInteger

(5) -> differentiate(ex1,x)

2
sin(x) - cos(x)
(5) ----------------
2
sin(x)
Type: UnivariatePolynomial(x,Expression Integer)

(6) -> ex2:=(x+1/sin(x))$DMP([x],EXPR INT)

1
(6) x + ------
sin(x)
Type: DistributedMultivariatePolynomial([x],Expression Integer)

(7) -> degree ex2

(7) [1]
Type: DirectProduct(1,NonNegativeInteger)

(8) -> differentiate(ex2,x)

(8) 1
Type: DistributedMultivariatePolynomial([x],Expression Integer)

The results for (5) and (8) should be identical... QED.
...
In fact I cannot see a single reason to consider a domain
DMP(vars, EXPR INT) at all, except for the fact that we do
not have a domain EXPR(vars, coefficients) yet.
How would you use such a domain to solve the problem originally
posed by Francois about expansion of trigonometric expressions
that started this thread? At the very least we would need
'DEXPR(vars, coefficients)',i.e. the "distributed" version.
But I have no objection to this suggestion. It is the other
things that we discovered about complicated nested types
along the way that concerns me now.
Post by Bill Page
Post by Martin Rubey
Note that b::UP([x], INT) or b::POLY INT give errors!
Obviouse 'b' has no representation in these domains.
Yes it has: 1 is a UP([x], INT).
No! 'b' for example in:

(9) -> P := UP(x, EXPR INT)

(9) UnivariatePolynomial(x,Expression Integer)
Type: Domain

(10) -> a :P := x

(10) x
Type: UnivariatePolynomial(x,Expression Integer)

(11) -> b := a/x

1
(11) - x
x
Type: UnivariatePolynomial(x,Expression Integer)

is not the same a '1$P'

Regards,
Bill Page.
Martin Rubey
2006-02-23 11:00:57 UTC
Permalink
In mathematics, a polynomial is an expression in which constants
and variables are combined using (only) addition, subtraction,
and multiplication. Thus, 7x^2+4x-5 is a polynomial; 2/x is not.
I think this definition is less general it needs to be and difficult to apply
in the context of Axiom. We need to know what are "constants" and what are
"variables" and where "addition", "subtraction" and "multiplication" are
defined.
I recall that in the Algebra course I attended, the polynomial
ring was defined as a ring (of coefficients) together with a
variable which is to be transcendent over that ring.
That definition is much better. In the case we are discusing the ring of
coefficients is the domain 'EXPR INT' which includes expressions of the form
'1/x' and so it is correct to say that '2/x' is not in itself a polynomial
but it can be a coefficient in a polynomial.
Yes, but the variable of the polynomial needs to be transcendent over the
coefficient domain. So we have to have two different x here.
sin x + y*cos x + y^2* tan x
is perfectly allright a polynomial in y.
I agree, but it is also a perfectly good polynomial in x provided that it can
NO! It is not a polynomial in x.
(1) -> (sin x + y*cos x + y^2* tan x)$UP(x,EXPR INT)
2
(1) y tan(x) + sin(x) + y cos(x)
Type: UnivariatePolynomial(x,Expression Integer)
(2) -> degree %
(2) 0
Type: NonNegativeInteger
Yes, but the x of UP(x, EXPR INT) is a different x than the x in sin(x). They
only happen to have the same name.
Of course, if you claim that x+1/sin(x) is a polynomial, than I'm out of
luck.
Indeed, I think you are out of luck. :(
Why? Are you really saying that x+1/sin(x) is a polynomial in x? Once more: the
polynomial variable needs to be transcendent over the coefficient domain. The
reason is simple: otherwise you lose all the interesting features of
polynomials, for example, that you can easily test for equality, given a test
for equality in the coefficient domain.
(3) -> ex1:=(x+1/sin(x))$UP(x,EXPR INT)
1
(3) x + ------
sin(x)
Type: UnivariatePolynomial(x,Expression Integer)
(4) -> degree ex1
(4) 1
Type: PositiveInteger
(5) -> differentiate(ex1,x)
2
sin(x) - cos(x)
(5) ----------------
2
sin(x)
Type: UnivariatePolynomial(x,Expression Integer)
(6) -> ex2:=(x+1/sin(x))$DMP([x],EXPR INT)
1
(6) x + ------
sin(x)
Type: DistributedMultivariatePolynomial([x],Expression Integer)
(7) -> degree ex2
(7) [1]
Type: DirectProduct(1,NonNegativeInteger)
(8) -> differentiate(ex2,x)
(8) 1
Type: DistributedMultivariatePolynomial([x],Expression Integer)
The results for (5) and (8) should be identical... QED.
(What are you proving here?)

Yes, they should be identical, and I vote for (8). Well, in fact I vote for not
using a construction like DMP([x], EXPR INT). What I would find nice though
would be a way to say: have a polynomial in x with coefficients beeing
arbitrary expressions which do not contain the variable x. (In this case, the
result of (5) would indeed be 1.)

There are several problems with the UP domain, for example, try

(27) -> ex3:=(y+1/sin(x))$UP(y,EXPR INT); differentiate(ex3, x)

2
sin(x) - cos(x)
(27) ----------------
2
sin(x)
Type: UnivariatePolynomial(y,Expression Integer)
At the very least we would need 'DEXPR(vars, coefficients)',i.e. the
"distributed" version. But I have no objection to this suggestion.
Great.
It is the other things that we discovered about complicated nested types
along the way that concerns me now.
Great.

Martin
Ralf Hemmecke
2006-02-24 10:12:18 UTC
Permalink
Post by Bill Page
Perhaps I should have said this differently. Yes, I do agree that
the 'x' in '1/x' and '2*x' are different. But they are not
different in the sense in which 'x' and 'y' are different, i.e.
they are not different variables - they are the same variable
used in two different ways.
What is a variable anyway? Roughly speaking, it is something that has
just a name. Some people like variables to behave transcendentally.

Let us take again the view that a polynomial ring "R[x]" (it's in quotes
since I haven't defined that notation yet) is the ring

P = \bigoplus_{e \in N} R

where N are the non-negative integers.
Elements in P (the polynomials) are just functions with finite support
from N to R. So the are nothing else than (infinite) sequences of
numbers from R where only a finite non-zeros appear.

Now, let x \in P be such that x(1)=1 and x(e)=0 for e \in N\setminus\{1\}.

If you like, you can consider this x to be the "indeterminate" or
"variable" of P.

It is also clear that by construction this x is different from anything
that lives in R.

Further, if you take a ring R and a monoid M then there is the monoid
ring RM which consists of all (finite) R-linear combinations of
elements of M. (Well, R and M have to subsets of some common (bigger)
ring S such that this construction makes sense.)
Note that it is nowhere said that M must contain an element that is not
in R. But, of course, with the above construction RR = R.

If [x] with the x from above is the free (abelian) monoid generated by
x, then R[x] is a polynomial ring.


**What is differentiation in P?**

(That is a bit informal here.)
Given that elements in P have finite support, we can represent them as
finite tuples. Let a := (a_0, a_1, ..., a_n) \in P, then the (formal)
derivative of a is

a' = (a_1, 2 a_2, 3 a_3, ..., n a_n)

(Note that a_0 is missing.)

If you write a as a formal sum, using the x introduced above, you get.

a = \sum_{e=0}^n a_e x^e

a' = \sum_{e=0}^{n-1} a_{e+1} x^e

just as expected.


I very much have the impression that Bill likes to treat polynomials as
functions in contrast to formal objects.

For example, let F be the Galois field with two elements. As polynomials
p(x) = x + 1 and q(x) = x^2 + 1 are clearly different since they have
different support. But as polynomial functions from F to F, they are equal.

p(0) = 1 = q(0), p(1) = 0 = q(1)



If we were to treat polynomials in R[x_1,...,x_n] as functions from R^n
to R, then I think it would be reasonable to differentiate also in the
coefficient domain (but first define exactly what differentiation is,
before such a domain is implemented).

I think that the current implementation of polynomials in Axiom more
closely follow the formal approach. If somebody wants polynomials to
behave differently, then there should be a clear documentation and an
**additional** domain that support these ideas. But, please don't modify
the existing polynomials in Axiom.
Post by Bill Page
Post by Martin Rubey
I guess you know that, so there is probably a misunderstanding
sin x + y*cos x + y^2* tan x
is perfectly allright a polynomial in y.
I agree, but it is also a perfectly good polynomial in x
provided that it can appear as a member of the coefficient
Bill, if this is your terminology, I strongly disagree with you.
If I say something is "polynomial in x" then I mean if the expression is
written as an expression tree then in the path from every x to the root
I should at most see "^", "*", "+" (and "-").
Post by Bill Page
(1) -> (sin x + y*cos x + y^2* tan x)$UP(x,EXPR INT)
2
(1) y tan(x) + sin(x) + y cos(x)
Type: UnivariatePolynomial(x,Expression Integer)
(2) -> degree %
(2) 0
Type: NonNegativeInteger
Yes, Axiom is correct _and_ confusing! If a user want to construct
something like UP(x,EXPR INT), then he should know what he is doing.
Unfortunately, beginners probably don't know what they do when they type
in UP(x,EXPR INT). And they will be surprise by the strange results. And
I very much think that they will turn their back to Axiom, because it is
so confusing. (Which would be a pity.)
Post by Bill Page
Post by Martin Rubey
Of course, if you claim that x+1/sin(x) is a polynomial, than
I'm out of luck.
Indeed, I think you are out of luck. :(
(3) -> ex1:=(x+1/sin(x))$UP(x,EXPR INT)
1
(3) x + ------
sin(x)
Type: UnivariatePolynomial(x,Expression Integer)
Just for fun... who else on the list votes for x+1/sin(x) to be a
"polynomial in x"? (Don't consider (3) when you vote.)
For me it's not a "polynomial in x". ;-)
Post by Bill Page
Post by Martin Rubey
Post by Bill Page
Post by Martin Rubey
Note that b::UP([x], INT) or b::POLY INT give errors!
Hey, if coerce: SOMETHING -> UP(x, INT) is a total function, then what
does that mean?
Post by Bill Page
Post by Martin Rubey
Post by Bill Page
Obviouse 'b' has no representation in these domains.
Does someone believe that "coerce" always has to be an inclusion function?
Post by Bill Page
Post by Martin Rubey
Yes it has: 1 is a UP([x], INT).
(9) -> P := UP(x, EXPR INT)
(9) UnivariatePolynomial(x,Expression Integer)
Type: Domain
(10) -> a :P := x
(10) x
Type: UnivariatePolynomial(x,Expression Integer)
(11) -> b := a/x
1
(11) - x
x
Type: UnivariatePolynomial(x,Expression Integer)
is not the same a '1$P'
What does that matter? If we have two domains A and B, two elements
a \in A, b \in B, a function coerce: A->B, and coerce(a) = b.
The whole relation between a and b is clear.
But where is it written, that coerce in Axiom has to be a homomorphism?
(BTW, a homomorphism of which type? Homomorphism of rings, of groups, of
sets?)

Ralf
Bill Page
2006-02-22 12:13:57 UTC
Permalink
Martin,
Post by Martin Rubey
I'm currently out of time. But I'm a little afraid of the
direction the discussion takes currently.
I on the other hand am very happy that this discussion
seems to accurately reflect the concept of type in Axiom.
Post by Martin Rubey
I believe that the intension of a constructor like DMP is
to cover *polynomials*.
I agree. "cover" is the operative word. This does not
preclude that the type DMP in Axiom might be a little more
general than what is called a polynomial in some mathematical
uses (but perhaps not others).
Post by Martin Rubey
If we allow (2*x+1/x)::DMP([x], EXPR INT), i.e., allowing 1/x
as a coefficient, then it must be clear that the "x" in 1/x
is something different than the "x" in 2*x. Otherwise we don't
get a polynomial, obviously.
I think this is wrong. In fact, it is clear from the
implementation of Axiom that whether the 'x' in these two
cases is the same or not depends on which domain to which
they belong.

Could you please define in what sense "Otherwise we don't get
a polynomial, obviously."? To me this is not obvious - it is
wrong.
Post by Martin Rubey
So, I think that
Post by Bill Page
Post by Francois Maltey
P := DMP([x,y], EXPR INT)
a :P := x
b := a/x
differentiate(b,x) -- 1/x
(4) -> differentiate(b,x)
1
(4) -
x
Type: DistributedMultivariatePolynomial([x,y],Expression Integer)
I think this result should be classed a bug. The 'differentiate'
operation apparently makes some incorrect assumptions about the
is not a bug. If you want to have axiom output 0, then I
imagine that you will get into trouble with writing packages,
variable capture might well occur.
If by "variable capture" you mean the same thing as "escaped
local variables", then I would claim that this can not occur in
Axiom, by nature of it's internal design.

On the other hand a 'differentiate' operator that returns 1/x
in (4) above would violate the mathematical definition of
derivative, so I think it cannot possibly be right.
Post by Martin Rubey
I'd rather say that b::EXPR INT giving one is troublesome. I
wouldn't really classify it as a bug though, given the nature
of EXPR INT.
No! EXPR INT is a domain in which we can ask with the two
uses of 'x' represent the same 'x' and we correctly discover
that in this context they are the same.
Post by Martin Rubey
Note that b::UP([x], INT) or b::POLY INT give errors!
Obviouse 'b' has no representation in these domains. This
result is correct. On the other hand one might expect that
'b::FRAC POLY INT' would work, but in this case I think it is
just a limitation of the conversion algorithm.
Post by Martin Rubey
PLEASE don't change the behaviour of DMP and company. What
should be documented (and I think Ralf did, but I hadn't time)
is that domains like POLY EXPR INT and friends can lead to
"surprising" results. This should go into the section "types"
of the axiom book.
Documentation is a good thing. But why should we retain behaviour
in Axiom that is mathematically incorrect? What advantage does
this odd behaviour of 'differentiate' have over a mathematically
correct implementation?

Regards,
Bill Page.
Bill Page
2006-02-23 16:05:03 UTC
Permalink
Martin,
...
Post by Bill Page
(1) -> (sin x + y*cos x + y^2* tan x)$UP(x,EXPR INT)
2
(1) y tan(x) + sin(x) + y cos(x)
Type: UnivariatePolynomial(x,Expression Integer)
(2) -> degree %
(2) 0
Type: NonNegativeInteger
Yes, but the x of UP(x, EXPR INT) is a different x than the
x in sin(x). They only happen to have the same name.
This is the core of our disagreement. I think you are wrong.
In Axiom it does not make sense to say they are "different but
have the same name". (This is possible in some other computer
algegra systems such as Maple and maybe MuPad.) In AxioM 'x'
is a symbol - at the deepest level it is still just a symbol
in Lisp. It can not have a different "name". This symbol can
be used in different ways but in the end, it is the **same**
symbol.

If you want, we could look at the Axiom source code itself to
verify that there is only one 'x' involved. You would see for
example that there is no call to Lisp to create any new
symbols. That might take some time.

But consider this example:

(1) -> P:=(x+1/x)$DMP([x],EXPR INT)

1
(1) x + -
x
Type: DistributedMultivariatePolynomial([x],Expression Integer)

(2) -> (variables(P)::List Symbol=variables(coefficient(P,0)))::Boolean

(2) true
Type: Boolean

--------

How else could you explain this result? 'variables(P)' is the
list of polynomial variables. 'variables(coefficient(P,0))' is
the list of variables occurring in the term with degree 0.

Regards,
Bill Page.
Page, Bill
2006-02-23 23:38:46 UTC
Permalink
Could you please define in what sense "Otherwise we don't
get a polynomial, obviously."? To me this is not obvious -
it is wrong.
Why should this be wrong?
In mathematics, a polynomial is an expression in which
constants and variables are combined using (only) addition,
subtraction, and multiplication. Thus, 7x^2+4x-5 is a
polynomial; 2/x is not.
I have the same point of view than Martin, everything is done
in DMP in order to have a polynomial ring, DMP isn't only a
<< collect >> command which factorise x and so.
I agree with you that DMP must be a polynomial ring.

In Axiom, when we define a polynomial we must say over what
ring the polynomial is defined. The first parameter of DMP
is a list of variables, the second parameter is the name of
a ring - any ring. It is usual to define, for example:

DMP([x,y],Integer)

where 'Integer' is the underlying ring. This means that we
will allow polynomials with variables 'x' and 'y' and where
the coefficients are integers.

And 'DMP([x,y],Integer)' itself is a ring.

'Expression Integer' is also a ring. 'Expression Integer'
includes expressions such as '1/x'.

So it makes sense to write:

'DMP([x,y],Expression Integer)' where now the coefficients
come from the ring 'Expression Integer'.

'DMP([x,y],Expression Integer)' is still a ring. Axiom will
not confuse the '1/x' which can occur as a coefficient, with
the 'x' or 'y' that appears as a polynomial variable.

Everything works as it should, no?
I think this definition is less general than it needs to
be and difficult to apply in the context of Axiom.
If we change DMP assumption, it's no more ring.
I do *not* propose to change the way DMP is implemented.
I think it is correct except for the way 'differentiate' is
defined.
We need to know what are "constants" and what are "variables"
So the same variable is forbidden in the constant ring.
I find it's a bug to allow DMP([X,Z], DMP([X,Y], INT))
It is not a bug. I hope that you agree that 'DMP([X,Y], INT)'
is a ring. That is all that is required for 'DMP([X,Z], ... )'
to be a polynomial. Axiom will keep [X,Z] that appears in
the polynomial separate from the [X,Y] that appear in the
coefficients of this polynomial.

That is why I said the definition of polynomial above is not
good for Axiom. Axiom does not implement the idea of "variable"
and a "constant" in this way.
I recall that in the Algebra course I attended, the
polynomial ring was defined as a ring (of coefficients)
together with a variable which is to be transcendent over
that ring.
That definition is much better. In the case we are discussing
the ring of coefficients is the domain 'EXPR INT' which
includes expressions of the form '1/x' and so it is correct
to say that '2/x' is not in itself a polynomial but it can
be a coefficient in a polynomial.
I don't think so, a polynomial ring has variables which are
not in the initial ring.
The polynomial ring is a different domain than the initial
ring. So I agree that the 'x' that appears as the polynomial
variable is different than the 'x' that appears in the
coefficient '1/x'. I do not like to say "variable" because
Axiom does not have any concept of variable outside of the
context of some domain. To speak in the most accurate way
possible, we must say that the same *symbol* 'x' is used in
two different ways.
The DMP error (for derivative) isn't in the derivative
function but in the fact that axiom accepts 1/x has
variable in DMP[x].
First you must agree that '1/x' is a member of the ring
'Expression Integer'. Yes?

In 'Expression Integer', the result of 'differentiate(1/x,x)'
is '-1/x^2'. Of course.

If DMP is defined over the ring 'Expression Integer' then
'1/x' can be a coefficient of the polynomial. Yes?

Comparing DMP (DistributedMultivariatePolynomial) to UP
(Univariate Polynomial), we see in the source code for UP it
states that if the ring over which a polynomial is defined is
itself a polynomial ring, then 'differentiate' in DMP is defined
as the 'DifferentialExtension' of 'differentiate' in the
underlying ring. This works correctly in the case of the
domain 'UnivariatePolynomial' but fails in the case of DMP
defined over only one variable even though these two domains
should be functionally equivalent. In the latter case DMP
treats '1/x' as if it was a constant.
And 1/x isn't transcendent over that ring because y=1/x is
solution of xy-1=0 in this field.
No, that is not true because

1
- x
x

is not 1 in DMP([x,y],EXPR INT) if '1/x' is the coefficient
and the 'x' on the right is the polynomial variable!

Perhaps that is what seems strange to you. The problem is that
you are not taking account of the *domain* in which these
expressions are defined.
Either we say to the user he _must_ be careful with this,
(only in the EXPR INTEGER field?)
Either monomial command of DMP reject 1/x coefficient if x is
a variable.
I think we must say to the user that he _must_ be careful because
Axiom strictly implements the concept of 'domain' (which is just
another way of saying that Axiom is strongly typed) but often in
mathematics this notion is used only informally, if at all.

The concept of domain allows us to be more precise when we
encounter expressions such as:

1
- x
x

Whether this expression is identical to 1 or not depends on the
domain. This distinction is very similar to whether we treat
'x * y * x' as equivalent to 'x^2*y'. This depends on whether
or not in this domain the operation '*' is commutative.
The real axiom accepts coefficients as 1/x in DMP ([x], EXPR INT)
because axiom EXPR INT isn't perfect, but it shouldn't.
But I'm sure it's a mistake to change derivative.
I do not propose to change the derivative. I expect that DMP
should treat the derivative of the polynomial as an extension
of the derivative of the underlying ring in the same way that
UP does this.
How would you use such a domain to solve the problem originally
posed by Francois about expansion of trigonometric expressions
that started this thread?
When we expand a trigonometric expression,
the question is a << linear one >> not a polynomial one.
We expand more often sin (4*x+5*y) than sin (x^2+x) ;
for sin (x^2+x) we use series.
Sure, but Axiom already defines the trigonometric expansion of
'sin(x^2+x)' in the same way as other systems such as Maple and
Mupad:

(1) -> expand sin(x^2+x)

2 2
(1) cos(x)sin(x ) + cos(x )sin(x)
Type: Expression Integer

Your question was about the proper treatment of expressions
involving terms like '1/x'. My point is that the Axiom domain
'DMP([x,y],EXPR INT)' treats '1/x' in the way that you need
for this expansion.

Regards,
Bill Page.
Page, Bill
2006-02-24 13:12:16 UTC
Permalink
Ralf,
...
Let us take again the view that a polynomial ring "R[x]" (it's
in quotes since I haven't defined that notation yet) is the
ring
P = \bigoplus_{e \in N} R
where N are the non-negative integers.
Elements in P (the polynomials) are just functions with finite
support from N to R. So the are nothing else than (infinite)
sequences of numbers from R where only a finite non-zeros appear.
Ignoring for now the details of multivariate polynomials, in
Axiom we would write:

P:=POLY R

where R is some Ring (such as INT).
Now, let x \in P be such that x(1)=1 and x(e)=0 for e \in
N\setminus\{1\}.
If you like, you can consider this x to be the "indeterminate"
or "variable" of P.
No, this is not quite complete. There is a function 'coerce'
such that 'coerce(x::Symbol)$P' \in P. Axiom displays both
this polynomial and the symbol in the same way except the
Type is different.
It is also clear that by construction this x is different
from anything that lives in R.
Yes, I agree with this. Except you say "numbers from R" which
could be miss-leading if R itself is a polynomial ring or a more
general ring (such as Axiom's EXPR INT).
...
**What is differentiation in P?**
(That is a bit informal here.)
Given that elements in P have finite support, we can represent
them as finite tuples.
Let a := (a_0, a_1, ..., a_n) \in P, then the (formal)
derivative of a is
a' = (a_1, 2 a_2, 3 a_3, ..., n a_n)
(Note that a_0 is missing.)
If you write a as a formal sum, using the x introduced above,
you get.
a = \sum_{e=0}^n a_e x^e
a' = \sum_{e=0}^{n-1} a_{e+1} x^e
just as expected.
The defintion of differentiation that concerns me is specified
with respect to some symbol, e.g.

differentiate:(POLY R, Symbol) -> POLY R

If R is a Ring (such as another polynomial ring) which also
allows for example 'coerce(x::Symbol)$R' (in Axiom we would
write 'R has PDRING Symbol') then it makes good sense, I think
to define this differentiaton as an extension of the
differentiation in R (DifferentialExtension). This is what
is done in some Axiom polynomial domains and not others.
...
I think that the current implementation of polynomials in
Axiom more closely follow the formal approach. If somebody
wants polynomials to behave differently, then there should
be a clear documentation and an **additional** domain that
support these ideas. But, please don't modify the existing
polynomials in Axiom.
I agree. But we not talking about changing the way polynomials
behave, we are trying to define how polynomials behave now
in Axiom. My claim is that they do not (at least not quite)
behave that way that some people here have described. So I
am trying to change their description. :)
Post by Bill Page
Post by Martin Rubey
I guess you know that, so there is probably a
sin x + y*cos x + y^2* tan x
is perfectly allright as a polynomial in y.
I agree, but it is also a perfectly good polynomial in x
provided that it can appear as a member of the coefficient
Bill, if this is your terminology, I strongly disagree with
you. If I say something is "polynomial in x" then I mean if
the expression is written as an expression tree then in the
path from every x to the root I should at most see "^", "*",
"+" (and "-").
You are right. My terminology was poor. But Axiom does not
have any domain consisting of an expression tree such as
you describe. This would be a much more restricted that the
current polynomial domains in Axiom.

What I should have written was perhaps:

"it is also a perfectly good polynomial over a ring that
allows such such expressions"

My point is that this is well-defined even if the same
symbol 'x' appears in both the underlying ring (i.e. in a
coefficient, and as the polynomial variable.
Post by Bill Page
(1) -> (sin x + y*cos x + y^2* tan x)$UP(x,EXPR INT)
2
(1) y tan(x) + sin(x) + y cos(x)
Type: UnivariatePolynomial(x,Expression Integer)
(2) -> degree %
(2) 0
Type: NonNegativeInteger
Yes, Axiom is correct _and_ confusing!
The confusion is relative to the presumptions that one has
about how Axiom works... ;)
If a user want to construct something like UP(x,EXPR INT),
then he should know what he is doing. Unfortunately, beginners
probably don't know what they do when they type in
UP(x,EXPR INT). And they will be surprise by the strange
results.
Perhaps, but I do not see any reason for beginners to use
such complicated domains.
And I very much think that they will turn their back to
Axiom, because it is so confusing. (Which would be a pity.)
But that *is* how Axiom was designed. You are suggesting
that we should change or at least suppress this part of
the design. I instead am trying to find some way to describe
the what Axiom does now in a way that is comprehesible to
as many Axiom users as possible.

I object in principle to the idea of "dumbing down" the
fundamental design of Axiom so that it only behaves in the
way naïve users expect. On the other hand, I would be
happy to see a new user interface for new Axiom users that
would focus on implementing the "principle of least surprize".
...
Hey, if coerce: SOMETHING -> UP(x, INT) is a total function,
then what does that mean?
...
Does someone believe that "coerce" always has to be an
inclusion function?
Post by Bill Page
...
1
(11) - x
x
Type: UnivariatePolynomial(x,Expression Integer)
is not the same a '1$P'
What does that matter? If we have two domains A and B, two
elements a \in A, b \in B, a function coerce: A->B, and
coerce(a) = b. The whole relation between a and b is clear.
But where is it written, that coerce in Axiom has to be
a homomorphism? (BTW, a homomorphism of which type?
Homomorphism of rings, of groups, of sets?)
'coerce' is a conversion that is intended to be automatically
applied by the interpreter presumably without the risk of
encuring any mathematical errors. So I think that at the
very least a coercion must be a morphism from A to B
that preserves the structure of A (i.e. a functor). B can
have however additional structure that is not in A. Perhaps
this is also true of other conversions (invoked by ::) when
we consider the algebraic properties of the possible result
"failed".

For example we can coerce INT -> FLOAT but we can only
convert FLOAT -> INT.

(1) -> X:INT:=1

(1) 1
Type: Integer

(2) -> Y:=X+1.1

(2) 2.1 <---- this is a coercion of INT to Float
Type: Float

(3) -> Y + 1 <---- Float is not coerced to INT

(3) 3.1
Type: Float

(4) -> Y::INT

Cannot convert from type Float to Integer for value
2.1

(4) -> Z:Float:=1

(4) 1.0
Type: Float

(5) -> Z::INT <---- this is a conversion of Float to INT

(5) 1
Type: Integer

Regards,
Bill Page.
Ralf Hemmecke
2006-02-24 14:14:49 UTC
Permalink
Hi Bill,
Post by Page, Bill
(4) -> Z:Float:=1
(4) 1.0
Type: Float
(5) -> Z::INT <---- this is a conversion of Float to INT
(5) 1
Type: Integer
Now, I learned something new. And maybe Axiom behaves here different
from Aldor.

In Aldor "Z::Integer" is just syntactic sugar for writing
"coerce(Z)@Integer" (which looks for a function

coerce: Float -> Integer

currently in scope and applies it).

In Aldor there is (almost) never a coercion (type cast) done
automatically. Of course you can write something like

aldor -gloop
#include "aldor"
#include "aldorinterp"
Z:SingleFloat := 1;

But there is no coercion involved. Since SingleFloat is of type
ArtithmeticType.

%10 >> SingleFloat has ArithmeticType
T @ Boolean
%11 >> ArithmeticType
@ Category == AdditiveType with
1: %
*: (%, %) -> %
^: (%, MachineInteger) -> %
commutative?: Boolean
one?: % -> Boolean
times!: (%, %) -> %
default
local copy?: Boolean == % has CopyableType
one?(a: %): Boolean == ..
times!(a: %, b: %): % == ..

The 1 is simply interpreted as the constant 1 in SingleFloat.

Now the following is also clear.

%14 >> Z := 2
.....^
[L14 C6] #1 (Error) No meaning for integer-style literal `2'.
%15 >> Z:=2.0
2 @ SingleFloat
%16 >> import from Integer
%17 >> Z := 2
.....^
[L17 C6] #1 (Error) There is no suitable interpretation for the expression 2
The context requires an expression of type SingleFloat.
The possible types of the right hand side (`2') are:
-- AldorInteger

I like that Aldor does nothing automatically.

Ralf

PS: To be correct there is one case that comes to my mind where the
Aldor compiler is a bit more relaxed.
See "Curtesy conversions" at
http://www.aldor.org/docs/HTML/chap7.html#6
Page, Bill
2006-02-24 19:39:45 UTC
Permalink
William
Post by William Sit
2*x + 1/x
would mean that there is only ONE x, the x means the same
thing throughout the expression.
Yes.
Post by William Sit
So
(1) -> (2*x+1/x)::DMP([x], EXPR INT)
2
2x + 1
(1) -------
x
DistributedMultivariatePolynomial([x],Expression Integer)
(2) -> degree(%)
(6) [0]
is perfectly correctly interpreted by Axiom. The entire
expression is a coefficient, in EXPR INT.
It is a correct interpretation, but it is not the only
possible interpretation. The reason it is interpreted as
entirely with 'EXPR INT' is because you used a conversion
'::' instead of a package call $. Axiom processes what is
inside the parenthesis first. Since there is no package
specification there, the interpreter assumes we are talking
about 'EXPR INT'. Then it applies the coercion from 'EXPR INT'
to 'DMP([x], EXPR INT)' which simply embeds the expression
as a term of degree 0.

Try this instead:

(1) -> (2*x+1/x)$DMP([x], EXPR INT)

1
(1) 2x + -
x
Type: DistributedMultivariatePolynomial([x],Expression Integer)

(2) -> monomials(%% 1)

1
(2) [2x,-]
x
Type: List DistributedMultivariatePolynomial([x],Expression Integer)

In this case we told Axiom to use only operations from the
domain 'DMP([x], EXPR INT)'. It sees '2*x' and selects the
'*' with signature '?*? : (Integer,%) -> %'. The result is
a term of degree 1. Then it looks at '1/x' and selects
'?/? : (%,Expression Integer) -> %'. The result is a term
of degree 0.

This also is correctly interpreted by Axiom. But these two
expressions are not equivalent in this domain.
Post by William Sit
However, I think Axiom is wrong in allowing that, since x,
being an indeterminate over EXPR INT, should not be in
EXPR INT.
I suppose what you are saying is that the ring over which
DMP is defined should not be 'EXPR INT' but rather
'SubDomain(EXPR INT, not member?(x::Symbol,variables(#1))'.
This is a possible definition but it seems unnecessarily
complicated. Further it would explicitly prevent the kind
of coercion that Axiom was apparently carefully designed
to do (see below).

There is no danger that Axiom will confuse the two uses of
'x' and to the user this result looks perfectly reasonable -
it looks like just a different way of formatting the
expression - but of course as "advanced users" we know the
difference is more subtle than that.
Post by William Sit
The coercion should simply fail, or end up in
FRAC DMP([x], EXPR INT).
I do not see how it could possibly end of in
'FRAC DMP([x], EXPR INT)' in either version of (1) above.
Post by William Sit
Note that even if the following is used, Axiom continues to
"retract" the x from 1/x to EXPR INT. This is simply wrong.
x:DMP([x], EXPR INT):=x
2*x + 1/x
degree(%)
[1]
It is not wrong. I agree that it might be unexpected if
one does not keep in mind the domains from which Axiom will
select functions. One might (incorrectly) thought that the
1/x must be evaluated in 'FRAC DMP([x],EXPR INT)' but once
again Axiom first considers the '/' function defined in
domain that it already knows: 'DMP([x],EXPR INT)' before it
attempts anything more complex. It discovers that it can
evaluate 1 in 'DMP([x],EXPR INT)' and that since 'x' is a
variable of type 'DMP([x],EXPR INT)', it knows that it can
always coerce such polynomials into 'EXPR INT'. This allows
it to apply the operator '/' from 'DMP([x],EXPR INT)'.
Post by William Sit
On the other hand, the following is correct, and should
be the case no matter what the coefficient domain is.
y:DMP([y], INT):=y
2*y+1/y
2
2y + 1
-------
y
Type: Fraction
DistributedMultivariatePolynomial([y],Integer)
The two cases should not be handled differently.
I agree that this result is correct but I disagree that
these two cases can be handled the same way (i.e. by
selecting the '/' operation in 'DMP([y], INT)'. This is
not possible because Axiom cannot coerce polynomials of
type 'DMP([y], INT)' into 'INT'.
Post by William Sit
If a user wants to push the result down to the coefficient
domain, it should be done with a substitution map,
explicitly, and the user should not use x in EXPR INT.
This sort of coercion is only possible when the coefficient
domain has 'PDRING Symbol' or at least 'PDRING OVAR vl'
where 'vl' is polynomial variable list. Apparently Axiom
attempts to use it during the function selection process.

Regards,
Bill Page.
Loading...