Joe Riel

9530 Reputation

23 Badges

20 years, 24 days

MaplePrimes Activity


These are answers submitted by Joe Riel

It is good practice to use the returnonly option to ListDirectory. Hence,
files := FileTools:-ListDirectory(path, 'returnonly' = "*.m"):
I prefer using sprint rather than cat, but that is a matter of taste:
for f in files do
   read sprintf("%s/%s", path, f);
end do:
Note that you can also use a forward slash rather than an escaped (doubled) backslash; Windows generally interprets it properly (I suspect one could embed forward slashes in the name of a file and cause problems, but...).
I realized, upon rereading the original post, that we answered the wrong question. He doesn't want to use next to exit more than one loop, rather he wants to use it to increment the counter more than its usual amount. That can be done directly:
for i to 10 do print(i); if i=5 then i:=i+1; next end if end do;
                                                       1
                                                       2
                                                       3
                                                       4
                                                       5
                                                       7
                                                       8
                                                       9
                                                      10
I don't know that I'd recommend that technique, it is potentially troublesome. Nicer might be to use your own loop counter:
cnt := 0;
while cnt < 10 do
   cnt := cnt+1;
   if cnt = 5 then cnt := cnt+1; next end if;
end do;
One can do fun stuff like
timelimit(0.001, proc() local i; for i to 2 do i := i/2; lprint(i) end do end());
1/2
3/4
7/8
15/16
31/32
63/64
127/128
255/256
...
I've occasionally wondered what is the "best" way to do this. Off-hand I can think of four techniques: use flags, use try/catch, use return in a local proc, and use the undocumented goto command. Here is an outline of each; following is comparison of their relative speed. Methods
useflags := proc()
local finished;
    do
        do
            finished := true;
            if finished then break end if
        end do;
        if finished then break end if
    end do
end proc:

usetry := proc()
    try
        do
            do
                error
            end do;
        end do;
    catch:
    end try
end proc:

useproc := proc()
    proc()
        do
            do
                return
            end do
        end do
    end proc()
end proc:

usegoto := proc()
    do
        do
            goto(999);
        end do
    end do;
    999:
end proc:
Comparison executed 106 times:
useflags  3.630
usetry    3.270
useproc   3.089
usegoto   2.790
The order is about what I expected (intuitively, it wasn't clear which of the try or proc methods would be better). Note that using flags will get worse with more nesting levels and actual loop evaluation.
whattype should never be used in a procedure. Use either type or ::. For example,
proc(s::set)
local a;
   for a in s do
      if a::integer then
          return a;
      end if;
   end do;
   NULL;
end proc:
That being said, a nicer way, and one that doesn't depend on the sorting of the set, is
proc(s::set)
   sort(convert(select(type, s, integer), 'list'))[1];
end proc;
Another possibility is
proc(s::set)
   min(select(type, s, integer)[]);
end proc
however, that will return -infinity, rather than NULL, if the set contains no integers. I haven't actually tested these, just wrote them up, so...
Neither approach is particularly, or even approximately, robust. As a minimum, you would want to restrict the indeterminates returned by indets to names, otherwise it will fail with, say, sin(x). Slightly better would be to also eliminate constants, so that, for example, Pi doesn't get returned. I'd also check for a single indeterminate. Hence something like
test := proc(h)
local vars;
   vars := indets(h,'And(name,Not(constant))');
   if nops(vars) > 1 then
      error "too many indeterminates";
   elif vars = {} then
      error "no indeterminates";
   end if;
   eval(h, op(vars)=1.1)
end proc:
If the indeterminate name is already known, which I suspect is the case, then unapply is the way to go.
More generally, use foldl:
n := 4:                           
f := add(k[i]*x[i],i=1..n);
                    f := k[1] x[1] + k[2] x[2] + k[3] x[3] + k[4] x[4]
foldl(int,f,seq(x[i]=0..1,i=1..n));
                    1/2 k[1] + 1/2 k[2] + 1/2 k[3] + 1/2 k[4]

So how'd you do it? Here's one approach. See Cartesian Product of Lists for a comparison of ways to compute the cartesian product of lists. The following CartProdSeq was taken from there.
CartProdSeq := proc(L::seq(list))
local Seq,i,j;
option `Copyright (C) 2007, Joseph Riel. All rights reserved.`;
    eval([subs(Seq=seq, foldl(Seq
                              , [cat(i,1..nargs)]
                              , seq(cat(i,j)=L[j],j=nargs..1,-1)
                             ))]);
end proc:
P := combinat[permute]([0,0,1,1]):
map(Matrix,CartProdSeq(P,P));
 [0    0    1    1]  [0    0    1    1]        [1    1    0    0] 
[[                ], [                ], ...,  [                ]]
 [0    0    1    1]  [0    1    0    1]        [1    1    0    0] 
Use combinat[permute] to generate a list of the permuations. To convert these to Vectors you could use map:
combinat[permute]([0,0,1,1]);
      [[0, 0, 1, 1], [0, 1, 0, 1], [0, 1, 1, 0], [1, 0, 0, 1], [1, 0, 1, 0], [1, 1, 0, 0]]
map(Vector, %);
                         [0]  [0]  [0]  [1]  [1]  [1]
                         [ ]  [ ]  [ ]  [ ]  [ ]  [ ]
                         [0]  [1]  [1]  [0]  [0]  [1]
                        [[ ], [ ], [ ], [ ], [ ], [ ]]
                         [1]  [0]  [1]  [0]  [1]  [0]
                         [ ]  [ ]  [ ]  [ ]  [ ]  [ ]
                         [1]  [1]  [0]  [1]  [0]  [0]
That add is faster is to be expected; sum usually calls add to do a discrete summation, certainly it will in this case because it won't find a symbolic expression. The following demonstrates this;
tprime := proc (s) if isprime(s) then s else 0 end if end proc:
debug(add):
sum('tprime'(k),k=1..1000);
execute add, args = eval(tprime(k),j = k), k = a .. b
                                     76127
You typed rctlnn as rcltnn in the procedure. Another way to refer to a procedure is to use 'procname'. Here is a rewrite of your code:
rctlnn := proc(n::nonnegint)
local j;
option remember;
uses combinat;
    if n = 0 then
        0
    else
        bell(n) + add(stirling2(n,j)*procname(j), j=2..n-1)
    end if;
end proc:

rctlnn(4);
                       95
It's frequently better to use add for this application. Because add has special evaluation rules, it doesn't evaluate its first argument before substituting the value of the dummy variable, so quotes are not needed:
add(tprime(n), n=1..12); 
                                     28
Possibly you want to do the following:
uv2xy := {u=2*x-3*y, v=-x+y}:
eqs_xy := [x=0, x=-3, y=x, y=x+1];
# solve for transformation equations
xy2uv := solve(uv2xy, {x,y}):
# transform equations
eqs_uv := eval(eqs_xy, xy2uv);
# collect u and v
map(eq -> collect((lhs-rhs)(eq), [u,v])=0, eqs_uv);
              [-u - 3 v = 0, -u - 3 v + 3 = 0, v = 0, v - 1 = 0]
The problem is that T cannot handle symbolic arguments. There are a few ways to work around this. One is to modify the assignment of T so that it does not generate an error if one or more of its arguments are symbolic. For example:
T := proc(w,r)
   if not (w::numeric and r::numeric) then return 'T'(w,r) end if;
   (w, r) -> rhs(Maximize(Profit(T, L, w, r), assume = nonnegative)[2][1]);
end proc:
This returns an unevaluated call to T if T is called with nonnumeric arguments. A simpler approach, which avoids modifying T, is to create a one parameter function and pass it to plot:
plot( r -> T(0.5,r), 0.3 .. 0.4);
Note that the second argument to plot is a "naked" range, there is no dummy parameter (i.e., r = 0.3..0.5). This can also be achieved by using the curry procedure:
plot(curry(T,0.5), 0.3 .. 0.4)
See its help page for details. One final method is to prevent premature evaluation of the expression T(0.5,r). That can be done by surrounding it with forward quotes:
plot('T(0.5,r)', r=0.3..0.5)
Note that there is not a unique solution. For example, -diff(f(x-y,z-y),x) - diff(f(x-y,z-y),z) is also a solution.
The error is in your assignment to Δy, it should be
Δy = n -> s*(sin(t[n])-y[n])*Δt/Λ(t[n],x[n],y[n])
You used x[n]
First 102 103 104 105 106 107 108 Last Page 104 of 114