Carl Love

Carl Love

28035 Reputation

25 Badges

12 years, 319 days
Himself
Wayland, Massachusetts, United States
My name was formerly Carl Devore.

MaplePrimes Activity


These are answers submitted by Carl Love

The pre-subscript and pre-superscript have no overall predefined meaning in Maple, although they may be given meaning by some packages. I suspect that even in these cases, this notation is only used for the display of the results and has no meaning computationally. For example, a pre-subscript is used in the prettyprinted display of hypergeometric functions when typesetting is set to extended:

interface(typesetting= extended);
hypergeom([a], [b], x);

You are free to assign to them any meaning that you want.

Here are procedures for extracting them:

PreSub:= (x::{name, name^anything})->
     if x::`^` then thisproc(op(1,x))
     elif x::indexed then thisproc(op(0,x))
     else parse(op([6,1], parse(substring(x, 2..))))
     end if
:

PreSuper:= (x::{name, name^anything})->
     if x::`^` then thisproc(op(1,x))
     elif x::indexed then thisproc(op(0,x))
     else parse(op([7,1], parse(substring(x, 2..))))
     end if
:

Please let me know if that gives you what you want. If you want them returned with their color intact, that's slightly different.

Use D:

g:= D(f);
g(2);

In the function f(x,t), x is the first variable, so the second derivative with respect to x is D[1,1](f). You have D[2](f), which means the first derivative with respect to the second variable. After correcting for this, you still have the problem that you have no initial conditions; you only have boundary conditions. One usually specifies that something special happens when t=0.

Functional iteration is done with @@, so you can make your plot with

plot([seq([k, nops((Y@@k)({}))], k= 1..20)], style= point, symbolsize= 24);

The speed of Y can be improved with a remember table. See ?remember.

Real programmers don't use untypeable variable names with silly hats on them.

I think that the point of the error message is that dsolve can't solve ODEs of arbitrary, unspecified differential order, although that point is sometimes made more explicit as in

dsolve(diff(y(x), [x$n]) = y(x), y(x));
Error, (in dsolve) unable to handle ODEs of undefined differential order

geom3d:-point~([A,B,C], [[4,5,5], [-9,4,7], [-3,-3,3]]):
geom3d:-line(L1, [A,B]):
geom3d:-line(L2, [C, [5,7,-4]]):
geom3d:-distance(L1,L2);

     (289/2315)*sqrt(2315)

Here's a conversion procedure:

IndicesToSubscripts:= e-> subsindets(
     e,
     'indexed',
     n-> cat(
          `if`(op(0,n)::'indexed', IndicesToSubscripts(op(0,n)), op(0,n)),
          __,
          `if`(hastype([op(n)], 'indexed'), IndicesToSubscripts~([op(n)]), [op(n)])[]
     )
):

Example use:

e:= x[1] + y[a][b[c]]:
IndicesToSubscripts(e);

(output suppressed)

lprint(%);

x__1+y__a__b__c

Ordinarily indets, subsindets, and evalindets (without the flat option) are inherently recursive, working their way through the expression tree, but indets doesn't seem to extract indices, so the recursion needs to be made explicit in my procedure above.

The command lprint will reveal the underlying structure of almost anything in Maple. So, use lprint(A).

Let TD represent t/d. Then t = d*TD, so you can use eval:

eval(Wr_over_p, t= d*TD);

If you want to plot this, you'll need to change pi to Pi. The lowercase version is just a meaningless symbol in Maple.

interface(prompt= "> ");

It is done by scaling the function by .4, using scaling= constrained, and scaling the tickmarks on axis[3] by .4:

T0:= (x,y,m)-> 20/Pi*sum((-1)^(n+1)/n*exp( n*Pi/10*y)*sin(n*Pi/10*x), n=1..m);
plot3d(
     .4*T0(x,y,50), x= 0..10, y= 0..10,
     scaling= constrained, axis[3]= [tickmarks= [2=5, 4=10]]
);

The procedure below handles, with the greatest possible generality, all cases of multivariate functional iteration. It uses a combination of unapply and eval, and can be used as a replacement for eval or `@@`. It is often far more efficient than `@@` because it uses a repeated squaring algorithm. As far as I can determine, this is the only usage of a repeated squaring algorithm for functional iteration.

Multivariate Functional Iteration

Author: Carl Love, 2016-Sep-05

restart:

 

These first two procedures simply exist to use remember tables to avoid repetition of suboperations during recursive calls to the main procedure.

unapplyR:= proc(f, v, S, $)
option cache;
     S~@unapply(f, v)
end proc:

 

#Convert from a list({name, name=anything}) to a list(name=anything),
#then extract the left and right sides of the list elements.
ListNameValue:= proc(v::list({name, name= anything}), $)
option cache;
local V:= (x-> `if`(x::'name', x=x, x))~(v);
     (V, (lhs~,rhs~)(V))
end proc:

 

MultivarIterate:= proc(
     f::list,
     v::And(
          list({name, name= anything}),
          #Check that the names are distinct and match f in length.
          satisfies(
               v-> (n-> n=nops(f) and n=nops((x-> `if`(x::name, x, lhs(x)))~({v[]})))
                    (nops(v))
          )
     ),
     {Simp::{identical(NULL), appliable}:= expand},
     {iters::nonnegint:= 2},
     {method::identical(linear, repeatedsquaring):= repeatedsquaring}
)
local q, r, F, Fx, V, R, L, S;
     (V,L,R):= ListNameValue(v);
     S:= `if`(Simp = NULL or Simp = expand and R::'list(numeric)', _-> _, Simp);
     Fx:= S~(eval(f,V));
     if iters = 0 then
          S~(R)
     elif iters = 1 then
          Fx
     elif iters = 2 or method = 'linear' then
          thisproc(f, L=~ Fx, ':-iters'= iters-1, ':-Simp'= S)
     else #Use repeated squaring.
          F:= unapplyR(f, L, S);
          q:= iquo(iters, 2, 'r');         
          thisproc(F(F(L[])[]), `if`(r=1, L=~ Fx, v), ':-iters'= q, ':-Simp'= S)
     end if
end proc:          

The procedure above could be made simpler if iters=1 and iters=2 weren't treated as special cases, but it wouldn't be as efficient.

 

Your example:

f:= [y, y*z - x, -15*x*y - x*z - x]:
v:= [x,y,z]:

The default number of iterations is 2, and the default simplifier is expand.

MultivarIterate(f, v);

[y*z-x, -15*x*y^2*z-x*y*z^2+15*x^2*y+x^2*z-x*y*z+x^2-y, 15*x*y^2+x*y*z-15*y^2*z+16*x*y-y]

MultivarIterate(f, v, Simp= NULL);

[y*z-x, (y*z-x)*(-15*x*y-x*z-x)-y, -15*y*(y*z-x)-y*(-15*x*y-x*z-x)-y]

MultivarIterate(f, v, Simp= NULL, iters= 3);

[(y*z-x)*(-15*x*y-x*z-x)-y, ((y*z-x)*(-15*x*y-x*z-x)-y)*(-15*y*(y*z-x)-y*(-15*x*y-x*z-x)-y)-y*z+x, -15*(y*z-x)*((y*z-x)*(-15*x*y-x*z-x)-y)-(y*z-x)*(-15*y*(y*z-x)-y*(-15*x*y-x*z-x)-y)-y*z+x]

A:= MultivarIterate(f, v, iters= 3);

[-15*x*y^2*z-x*y*z^2+15*x^2*y+x^2*z-x*y*z+x^2-y, -225*x^2*y^4*z-30*x^2*y^3*z^2-x^2*y^2*z^3+225*x*y^4*z^2+15*x*y^3*z^3+225*x^3*y^3+30*x^3*y^2*z+x^3*y*z^2-480*x^2*y^3*z-32*x^2*y^2*z^2+15*x*y^3*z^2+255*x^3*y^2+17*x^3*y*z-31*x^2*y^2*z+15*x*y^3*z+x*y^2*z^2+16*x^3*y-15*x^2*y^2-x^2*y*z-15*x*y^3+15*y^3*z-x^2*y-16*x*y^2+y^2-y*z+x, 225*x*y^3*z^2+15*x*y^2*z^3-450*x^2*y^2*z-30*x^2*y*z^2-15*x*y^3*z+14*x*y^2*z^2+15*y^3*z^2+225*x^3*y+15*x^3*z+15*x^2*y^2-29*x^2*y*z-31*x*y^2*z+15*x^3+16*x^2*y+16*y^2*z-16*x*y-y*z+x]

v0:= [1.3, 2.5, -0.7]:

eval(A, v=~ v0);

[147.3770, 34596.1163250, 7461.459000]

The procedure can perform numeric evaluation of the iterated function. This is often more efficient than symbolic iteration followed by numeric evaluation.

MultivarIterate(f, v=~ v0, iters= 3);

[147.3770, 34596.1163250, 7461.459000]

MultivarIterate(f, v=~ v0, iters= 8);

[0.203944206379806e57, 0.161058256445710e105, -0.804233613250701e88]

The procedure Forget isn't a necessary part of this computation. It's only purpose is to make the timings accurate.

Forget:= ()-> forget~([ListNameValue, unapplyR]):

Forget():

A1:= CodeTools:-Usage(MultivarIterate(f, v, iters= 8)):

memory used=1.50GiB, alloc change=1.38GiB, cpu time=2.37m, real time=46.19s, gc time=58.70s

Often it's the simplification that takes the vast majority of the time.

Forget():

A2:= CodeTools:-Usage(MultivarIterate(f, v, iters= 8, Simp= NULL)):

memory used=52.60KiB, alloc change=0 bytes, cpu time=0ns, real time=1000.00us, gc time=0ns

evalb(A1 = expand~(A2));

true

Forget():

A3:= CodeTools:-Usage(MultivarIterate(f, v, iters= 8, method= linear)):

memory used=119.34KiB, alloc change=0 bytes, cpu time=0ns, real time=1000.00us, gc time=0ns

evalb(A1 = A3);

true

map(eval, [A1,A2], v=~ v0);

[[0.203944206379810e57, 0.161058256445714e105, -0.804233613250713e88], [0.203944206379808e57, 0.161058256445713e105, -0.804233613250717e88]]

Note that the simplification or expansion of the symbolics causes slight changes in the last few digits of the numeric evaluations. I suspect that unexpanded forms are more accurate.

 

The evaluation point can be symbolic and/or partial.

MultivarIterate(f, [x= (p+q), y, z= 0], iters= 4, Simp= NULL);

[((-p-q)*(-15*(p+q)*y-p-q)-y)*(-15*y*(-p-q)-y*(-15*(p+q)*y-p-q)-y)+p+q, (((-p-q)*(-15*(p+q)*y-p-q)-y)*(-15*y*(-p-q)-y*(-15*(p+q)*y-p-q)-y)+p+q)*(-15*(-p-q)*((-p-q)*(-15*(p+q)*y-p-q)-y)-(-p-q)*(-15*y*(-p-q)-y*(-15*(p+q)*y-p-q)-y)+p+q)-(-p-q)*(-15*(p+q)*y-p-q)+y, -15*((-p-q)*(-15*(p+q)*y-p-q)-y)*(((-p-q)*(-15*(p+q)*y-p-q)-y)*(-15*y*(-p-q)-y*(-15*(p+q)*y-p-q)-y)+p+q)-((-p-q)*(-15*(p+q)*y-p-q)-y)*(-15*(-p-q)*((-p-q)*(-15*(p+q)*y-p-q)-y)-(-p-q)*(-15*y*(-p-q)-y*(-15*(p+q)*y-p-q)-y)+p+q)-(-p-q)*(-15*(p+q)*y-p-q)+y]

This example shows how the procedure can be used to evaluate a recurrence relation of higher-than-first order.

MultivarIterate([y, x+y], [x=0, y=1], iters= 99);

[218922995834555169026, 354224848179261915075]

combinat:-fibonacci(99);

218922995834555169026

Now I'll show that MultivarIterate using its default repeatedsquaring algorithm is much more efficient than `@@`, (which I suspect uses something akin to the linear algorithm).

CodeTools:-Usage((((x,y)-> (y,x+y))@@999999)(0,1)):

memory used=40.65GiB, alloc change=0 bytes, cpu time=97.89s, real time=58.99s, gc time=63.06s

Forget():

CodeTools:-Usage(MultivarIterate([y, x+y], [x=0, y=1], iters= 999999)):

memory used=3.58MiB, alloc change=0 bytes, cpu time=31.00ms, real time=31.00ms, gc time=0ns

 

 

Download MultivarIterate.mw

The function IsSubspace that you want isn't predefined in Maple, but it can be built as a one-liner from LinearAlgebra:-IntersectionBasis like this:

IsSubspace:= (U::set(Vector), V::set(Vector))->
     andmap(u-> LinearAlgebra:-IntersectionBasis([u, V]) <> {}, U)
:

And it's used like this:

IsSubspace({<0,1,0>, <0,0,1>}, {<1,0,0>, <0,1,0>, <0,0,1>});

     true

An approach that would be more computationally efficient would be based on examining the row-echelon form of the matrix formed by the columns of V on the left augmented by the columns of U on the right. I don't feel like coding that right now, but I suspect that it could be done also as a one-liner using LinearAlgebra:-LinearSolve. I'll do it tomorrow, if someone else doesn't do it first.

The output of both procedures is now 0, 0, 1, 1. That's because assign is now built-in, and thus it can alter an environment variable. In earlier Maple, assign was written in Maple, so it any change that it made to an environment variable would revert as soon as assign exited.

If you want to see any output in a simple form, use lprint.

int(1/(x-a)/(x-b), x= -infinity..infinity);
lprint(%);

piecewise(And(a = RootOf(Im(_Z)), b = RootOf(Im(_Z))), undefined, Im(a) = 0, undefined, Im(b) = 0, undefined, I*Pi*(signum(0, Im(a), 1)-signum(0, Im(b), 1))/(a-b))

I suspect that the symbol that you were having trouble undetstanding is the script I that Maple uses to prettyprint Im.

First 211 212 213 214 215 216 217 Last Page 213 of 395