On Thu, Jul 04, 2024 at 06:28:01PM +0200, Ralf Hemmecke wrote:
> On 7/4/24 16:41, Waldek Hebisch wrote:
> > > Opinions? Should I try to come up with a proper fix? I somehow
> > > feel such a change will have quite some consequences in different
> > > part of FriCAS.
> >
> > Impact should be limited. Functions in AlgebraicManipulations are
> > mostly "user level" functions. It seems that 'ratDenom' and 'rootSimp'
> > are called from rest of algebra.
>
> OK, then I propose the attached patch. Admittedly, I have not looked
> deep into the Expression related stuff, so I hope that someone more
> familiar with Expression looks over it.
<snip>
> This, of course, assumes that "rootkernels tower x" returns the kernels
> from the leaves to the root.
Actually, I am not sure if this is true in corner cases. But
basically all expresion code expects such behaviour, so if needed
we should fix tower so that this holds.
> > As you noticed 'ratDenom' may be unreliable, so probably we should
> > replace is by something else in most of algebra.
>
> That would be good. The reason why I am currently looking into it is
> that I want some kind of normal form for AlgebraicNumber. In my
> computations there appear two of them in different form and I would like
> to be able to verify that they are equal (and, of course, it looks
> better, if the output is visually small). I don't need to solve every
> case but nested sqrt and nthRoot(..., 3) would already be a good progress.
So, basically you want 'normalize' to work with algebraic expression.
That is high priority item on my toto list.
> > Concerning 'rootSplit', it make sense to create better implementation.
>
> It seems that rootFactor actually also covers rootSplit. But probably
> rootSplit was supposed to do things without factorization.
Yes.
> Anyway, if you agree with the way I "solve" the problem, I can look at
> the other cases.
I would do this somewhat differently. Untested code below:
rootExpand(lk, lv, k) ==
x := first argument k
n := second argument k
op := operator k
x := eval(x, lk, lv) --> eval here
op(numer(x)::F, n) / op(denom(x)::F, n)
rootSplit x ==
lk0 := rootkernels tower x
lk : List(K) := []
lv : List(F) := []
for k in lk0 repeat
v := rootExpand(lk, lv, k)
lk := cons(k, lk)
lv := cons(v, lv)
eval(x, lk, lv)
What is the difference? Main is that eval is done _before_ solitting,
that allows cancellation between numerator and denominator. And
little differences like using 'cons' to _prepend_ to a list. Compared
to concat this avoids quadratic behaviour. Not very important here,
but IMO it is good to keep style consistent and this is normal
style in FriCAS code.
> > My impression is that original AlgebraicManipulations just used very
> > simple tricks to get functionality similar to what other CAS-es offerd.
> > But it was very limited.
>
> Yes. But I think, if we agree that AlgebraicManipulations should stay at
> top-level, i.e., convenience functions for users and not otherwise used
> in the algebra library, then we should make those functions as
> convenient as possible to assist the user in transforming expressions in
> the way they want them.
Yes it makes sense to improve them.
> > There are now some extentions and enhancements, but it is still
> > limited.
>
> What do you mean here?
I added rootFactor, there were various improvements, especially
by Qian. But the approach looks limited, I do not see how to
extend it to do things which and be done using different approach.
And to that matter, unstated assumption is that user can do
desired transformation by sequence of simpler transformations.
Currently I think that _single_ say 'transform' function with
many options would be better. The point is that multiple options
are simpler both for user and implementation than multiple
functions. And interactions of options can produce results
that would be hard to do as sequence of transformations.
--
Waldek Hebisch