On 09/15/2017 04:23 AM, oldk1331 wrote:
> I reviewed the patch, it's good

Thanks for the review.

I'll push my patch tonight.

> I then took a profile, to my surprise, almost 30% time is spent on
> |DIRPROD;subtractIfCan;2$U;17| and |NNI;subtractIfCan;2$U;4|,
> see the 'subtractIfCan' calls in gbintern.spad.  That function is
> implemented in vector.spad
> 
>   subtractIfCan(u:%, v:%):Union(%,"failed") ==
>          w := new(dim, 0)$Vector(R)
>          for i in 1..dim repeat
>             (c := subtractIfCan(qelt(u, i)$Rep, qelt(v,i)$Rep)) case "failed" 
> =>
>                     return "failed"
>             qsetelt!(w, i, c::R)$Rep
>          w pretend %
> 
> It has 2 problems:
> 1. it allocs the 'w' first, which very likely will not be used.
> 2. subtractIfCan for NNI is very wasteful, the return type
> Union("failed", NNI) takes 3 times the space than NNI.
> (type Maybe doesn't have this problem, but that's a different topic)
> 
> I changed it to (subtractIfCan2 is integer subtraction)
> 
>          subtractIfCan(u:%, v:%):Union(%,"failed") ==
>           for i in 1..dim repeat
>             qelt(u, i)$Rep < qelt(v,i)$Rep=>
>                     return "failed"
>           map(subtractIfCan2$R, u, v)
> 
> together with other small optimization, I managed to speed it up to
> 443 seconds (saves 40% time).

That's wonderful, but although your patch certainly works for NNI, I am
a bit worried, because in general it assumes that < is compatible with
addition/subtraction.

The specification of subtractIfCan

    subtractIfCan(x, y) returns an element z such that z+y=x or “failed”
    if no such element exists.

does, however, not have such a connection. And neither the specification
of + nor that of < makes such a connection. The connection is only
stated in OrderedAbelianMonoid from which OrderedAbelianMonoidSup
inherits. The latter one is the argument type of Expon in
GroebnerPackage. So your patch is fine, but somehow at the wrong place.
Or rather it must be made conditional

  if R has CancellationAbelianMonoid then
    if R has OrderedAbelianMonoidSup then
       subtractIfCan(u:%, v:%):Union(%,"failed") ==
         for i in 1..dim repeat
           qelt(u, i)$Rep < qelt(v,i)$Rep=>
                   return "failed"
         map(subtractIfCan2$R, u, v)
    else
      subtractIfCan(u:%, v:%):Union(%,"failed") ==
        w := new(dim, 0)$Vector(R)
        for i in 1..dim repeat
        (c := subtractIfCan(qelt(u, i)$Rep, qelt(v,i)$Rep)) case "failed" =>
                  return "failed"
        qsetelt!(w, i, c::R)$Rep
        w pretend %

In fact, for the most common Groebner computations R is NNI, so I guess,
it even makes sense to have specialized code for it. So then
map(subtractIfCan2$R, u, v) simply becomes something like u-v.
There are a few places in gbintern.spad where it simply says

  subtractIfCan(a, b) :: Expon

so subtraction is expected not to fail. Unfortunately, there is no other
export like subtract: (%, %) -> % which gives an error if subtraction is
failing. Such a subtract function would be better in case it is already
known that subtraction will not fail, like in the GB case.

Speaking of subtraction. In VectorCategory I see

    if R has AbelianGroup then
      - u                 == map(x +-> - x, u)
      n : Integer * u : % == map(x +-> n*x, u)
      u - v           == u + (-v)

That's fine in mathematically, but in Vector I don't see that
specialised. In other words each subtraction of two vectors allocates 2
new arrays, where one would certainly be enough.

Ralf




-- 
You received this message because you are subscribed to the Google Groups 
"FriCAS - computer algebra system" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To post to this group, send email to [email protected].
Visit this group at https://groups.google.com/group/fricas-devel.
For more options, visit https://groups.google.com/d/optout.

Reply via email to