acer

32343 Reputation

29 Badges

19 years, 328 days
Ontario, Canada

Social Networks and Content at Maplesoft.com

MaplePrimes Activity


These are replies submitted by acer

I often get a feeling of surprise that floating-point accuracy (as opposed to working precision!) does not come up on here on mapleprimes as a topic of intense discussion.

Routines such as evalf/Int and Optimization's exports have numerical tolerance parameters. And "atomic arithmetic operations", single calls to trig, and some special functions compute results accurate within so many ulps. But other than that, for compound expressions, all bets are off. The expression might be badly conditioned for floating-point evaluation.

Now, Maple has Digits as a control over working precision but it has no more general specifier of requested accuracy. Compare with Mathematica, which claims to have both. So, in Maple one must either do analysis or raise Digits to some problem-specific mystery value. The evalr command (and its less well-known friend, shake) is not really strong enough to help much. An argument that I have sometimes heard against making any progress in this area is that its an open field of study, and partial, fuzzily-bounded coverage is to be avoided. If we all accepted that sort of thinking all the time, Maple might have normal but no radnormal, evala/Normal, simplify/trig let alone simplify proper.

acer

I often get a feeling of surprise that floating-point accuracy (as opposed to working precision!) does not come up on here on mapleprimes as a topic of intense discussion.

Routines such as evalf/Int and Optimization's exports have numerical tolerance parameters. And "atomic arithmetic operations", single calls to trig, and some special functions compute results accurate within so many ulps. But other than that, for compound expressions, all bets are off. The expression might be badly conditioned for floating-point evaluation.

Now, Maple has Digits as a control over working precision but it has no more general specifier of requested accuracy. Compare with Mathematica, which claims to have both. So, in Maple one must either do analysis or raise Digits to some problem-specific mystery value. The evalr command (and its less well-known friend, shake) is not really strong enough to help much. An argument that I have sometimes heard against making any progress in this area is that its an open field of study, and partial, fuzzily-bounded coverage is to be avoided. If we all accepted that sort of thinking all the time, Maple might have normal but no radnormal, evala/Normal, simplify/trig let alone simplify proper.

acer

This is shorter than what I had before, but still multiplies and divides by exp(t). Of course, it also does ln-of-exp as another "arbitrary" operation-with-its-inverse.

> ee:=ln(cosh(t)):

> combine(simplify(expand(
>   ln(exp(t)*expand(exp(-t)*(exp(convert(ee,exp)))))
>                         ))) assuming real;
                          ln(1/2 + 1/2 exp(-2 t)) + t

> # or, using 1/exp(t), showing nonreliance at least upon the exp "form".
> combine(simplify(expand(
>   ln(exp(t)*expand(1/exp(t)*(exp(convert(ee,exp)))))
>                         ))) assuming real;
                          ln(1/2 + 1/2 exp(-2 t)) + t

acer

This is shorter than what I had before, but still multiplies and divides by exp(t). Of course, it also does ln-of-exp as another "arbitrary" operation-with-its-inverse.

> ee:=ln(cosh(t)):

> combine(simplify(expand(
>   ln(exp(t)*expand(exp(-t)*(exp(convert(ee,exp)))))
>                         ))) assuming real;
                          ln(1/2 + 1/2 exp(-2 t)) + t

> # or, using 1/exp(t), showing nonreliance at least upon the exp "form".
> combine(simplify(expand(
>   ln(exp(t)*expand(1/exp(t)*(exp(convert(ee,exp)))))
>                         ))) assuming real;
                          ln(1/2 + 1/2 exp(-2 t)) + t

acer

You've started with lots of the interesting bits already done, such as gracefully pulling out that exp(t) factor while keeping exp(-2*t) instead of 1/exp(t^2).

So, one can do it by first multiplying by exp(-t), then multiplying shortly after by exp(t). But I consider that a kludge since it's not fully automatic -- it sorta depends on fortuitously choosing that particular factor of exp(t) to introduce. And still there can be the problem of multiplying through by the exp(-t) and getting exp(-2*t) rather than 1/exp(2*t).

Below the intermediate conversion back to trigh is there merely to allow the exp(-t) factor to survive multiplication by exp(t). Quite ugly, all told.

> ee:=ln(cosh(t)):

> exp(t)*convert(exp(-t)*(exp(convert(ee,exp))),trigh);
                                     2
                      exp(t) (cosh(t)  - sinh(t) cosh(t))
 
> combine(simplify(convert(expand(ln(%)),exp))) assuming real;
                          t + ln(1/2 + 1/2 exp(-2 t))

acer

You've started with lots of the interesting bits already done, such as gracefully pulling out that exp(t) factor while keeping exp(-2*t) instead of 1/exp(t^2).

So, one can do it by first multiplying by exp(-t), then multiplying shortly after by exp(t). But I consider that a kludge since it's not fully automatic -- it sorta depends on fortuitously choosing that particular factor of exp(t) to introduce. And still there can be the problem of multiplying through by the exp(-t) and getting exp(-2*t) rather than 1/exp(2*t).

Below the intermediate conversion back to trigh is there merely to allow the exp(-t) factor to survive multiplication by exp(t). Quite ugly, all told.

> ee:=ln(cosh(t)):

> exp(t)*convert(exp(-t)*(exp(convert(ee,exp))),trigh);
                                     2
                      exp(t) (cosh(t)  - sinh(t) cosh(t))
 
> combine(simplify(convert(expand(ln(%)),exp))) assuming real;
                          t + ln(1/2 + 1/2 exp(-2 t))

acer

Hi Doug,

Thanks for the interesting write-up.

I was wondering what you might be able to report about two items that you have yourself mentioned here in the past.

The first relates to the inability to download .mw files using Microsoft Outlook's webmail access, which you reported as a serious restriction for your university's use of Maple in courses.

The second relates to a post you made about using Maplet's vs Embedded Components, in which you mentioned the clear lack of programmatic control of Embedded Components.

May I ask, did you bring up these subjects?

acer

What I was trying to get at before is that testing for the difference of two expressions' being zero is a more practical general strategy than trying to simplify one form to the other with a general manipulation rule.

Nobody is going to argue -- sensibly, I suppose -- about the "simplest" form of an expression the is exactly equal to zero. So rather than wonder what is the "simplest" form of either the RHS or the LHS of your (here, trigonometric) equation, you can instead subtract them and test for zero.

acer

What I was trying to get at before is that testing for the difference of two expressions' being zero is a more practical general strategy than trying to simplify one form to the other with a general manipulation rule.

Nobody is going to argue -- sensibly, I suppose -- about the "simplest" form of an expression the is exactly equal to zero. So rather than wonder what is the "simplest" form of either the RHS or the LHS of your (here, trigonometric) equation, you can instead subtract them and test for zero.

acer

For fun, and to show how very many ways there are,

<Matrix(5,shape=scalar[1])>;

The extra <..> is to get a Matrix without any indexing function.

Sorry, It hasn't been clear to me whether you wanted f(i,i) or merely introduced `f` as some way to try and get the value of 1 along the diagonal.

acer

For fun, and to show how very many ways there are,

<Matrix(5,shape=scalar[1])>;

The extra <..> is to get a Matrix without any indexing function.

Sorry, It hasn't been clear to me whether you wanted f(i,i) or merely introduced `f` as some way to try and get the value of 1 along the diagonal.

acer

That is not quite right. It's not just a question of replacing the _Inert_LOCALSEQ call. The locals have to be changed from _Inert_NAME to _Inert_LOCAL and the relvant argument changed from a string to an ordinal. And subsop(2=...) doesn't serve, as that is only allowed when the number of locals remains the same, I believe.

(Perhaps see my code above, or try your code on my example procecdure f therein.)

It seems that Doug's guess was correct in any event, and that instead of blowing lexical scoping out of the water the OP merely wanted to supress the warnings due to automatic/implicit local declaration. I guess that using a term like "variable" in a Maple discussion is a bit like using the term "germ" in a conversation with an epidemiologist or microbiologist.

acer

That is not quite right. It's not just a question of replacing the _Inert_LOCALSEQ call. The locals have to be changed from _Inert_NAME to _Inert_LOCAL and the relvant argument changed from a string to an ordinal. And subsop(2=...) doesn't serve, as that is only allowed when the number of locals remains the same, I believe.

(Perhaps see my code above, or try your code on my example procecdure f therein.)

It seems that Doug's guess was correct in any event, and that instead of blowing lexical scoping out of the water the OP merely wanted to supress the warnings due to automatic/implicit local declaration. I guess that using a term like "variable" in a Maple discussion is a bit like using the term "germ" in a conversation with an epidemiologist or microbiologist.

acer

Actually, it doesn't work like that in general. Maple will automatically declare the name as local if it is assigned to. But if it is merely used, without assignment, then it gets its value at runtime via Maple's lexical scoping rules.

It is possible to rewrite a proc and turn undeclared names into declared locals. Below is a crude example of this. (It is crude in the sense that it likely needs a lot more polishing in order to handle more complicated examples properly, etc. One can very likely break it easily.)

> convloc:=proc(f)
> local oldlocs,newlocs,newf,i;
> oldlocs:=map(convert,{op(2,eval(f))},string);
> newlocs:=map(op,indets(ToInert(eval(f)),specfunc(anything,_Inert_NAME)))
>   minus {"protected", _Inert_ATTRIBUTE(_Inert_NAME("protected"))}
>   minus map(convert,{op(1,eval(f))},string)
>   minus oldlocs;
> newf := ToInert(eval(f));
> for i from 1 to nops(newlocs) do;
>   newf := subsindets(newf,specfunc(newlocs[i],_Inert_NAME),
>                      t->_Inert_LOCAL(i+nops(oldlocs)));
> end do;
> FromInert(subs(_Inert_LOCALSEQ(seq(_Inert_NAME(ZZ),ZZ in oldlocs))
>                =_Inert_LOCALSEQ(seq(_Inert_NAME(ZZ),ZZ in oldlocs),
>                                 seq(_Inert_NAME(ZZ),ZZ in newlocs)),
>                newf));
> end proc:
>
> f:=proc(x)
> local p;
> p := T; seq(i, i = 1 .. 2); NULL;
> end proc;
        f := proc(x) local p; p := T; sum(i, i = 1 .. 2); NULL end proc

>
> convloc(f);
       proc(x) local p, T, i; p := T; sum(i, i = 1 .. 2); NULL end proc

NB. BY "assigned to" I mean with the assignment statement, using := syntax. With the `assign` command, Maple will not automatically declare the name. But that's is just one of several subtleties to using `assign` inside a proc, which should usually be avoided unless one knows the system well.

> restart:
> f := proc()
> assign(a,b);
> end proc;
                       f := proc() assign(a, b) end proc

acer

Actually, it doesn't work like that in general. Maple will automatically declare the name as local if it is assigned to. But if it is merely used, without assignment, then it gets its value at runtime via Maple's lexical scoping rules.

It is possible to rewrite a proc and turn undeclared names into declared locals. Below is a crude example of this. (It is crude in the sense that it likely needs a lot more polishing in order to handle more complicated examples properly, etc. One can very likely break it easily.)

> convloc:=proc(f)
> local oldlocs,newlocs,newf,i;
> oldlocs:=map(convert,{op(2,eval(f))},string);
> newlocs:=map(op,indets(ToInert(eval(f)),specfunc(anything,_Inert_NAME)))
>   minus {"protected", _Inert_ATTRIBUTE(_Inert_NAME("protected"))}
>   minus map(convert,{op(1,eval(f))},string)
>   minus oldlocs;
> newf := ToInert(eval(f));
> for i from 1 to nops(newlocs) do;
>   newf := subsindets(newf,specfunc(newlocs[i],_Inert_NAME),
>                      t->_Inert_LOCAL(i+nops(oldlocs)));
> end do;
> FromInert(subs(_Inert_LOCALSEQ(seq(_Inert_NAME(ZZ),ZZ in oldlocs))
>                =_Inert_LOCALSEQ(seq(_Inert_NAME(ZZ),ZZ in oldlocs),
>                                 seq(_Inert_NAME(ZZ),ZZ in newlocs)),
>                newf));
> end proc:
>
> f:=proc(x)
> local p;
> p := T; seq(i, i = 1 .. 2); NULL;
> end proc;
        f := proc(x) local p; p := T; sum(i, i = 1 .. 2); NULL end proc

>
> convloc(f);
       proc(x) local p, T, i; p := T; sum(i, i = 1 .. 2); NULL end proc

NB. BY "assigned to" I mean with the assignment statement, using := syntax. With the `assign` command, Maple will not automatically declare the name. But that's is just one of several subtleties to using `assign` inside a proc, which should usually be avoided unless one knows the system well.

> restart:
> f := proc()
> assign(a,b);
> end proc;
                       f := proc() assign(a, b) end proc

acer

First 470 471 472 473 474 475 476 Last Page 472 of 592