Robert Israel

6577 Reputation

21 Badges

18 years, 212 days
University of British Columbia
Associate Professor Emeritus
North York, Ontario, Canada

MaplePrimes Activity


These are replies submitted by Robert Israel

Indeed. A simpler example is this:
> f:= x -> A:
  is (f(x) > 0) assuming A > 0;
false The help page ?assuming,details says
The assuming command does not scan programs regarding the presence of assumed variables; for that purpose use assume. Consider
> f := proc(x) sqrt(a^2)+x end proc;  # a Maple procedure (program)
f := proc(x) sqrt(a^2) + x end proc
The variable a is inside the body of f; the assumption that a > 0 is not effectively used when computing f(1).
> f(1) assuming a > 0;
(a^2)^(1/2)+1
For these purposes, use assume.
So this is a design decision, not a bug. Nevertheless, it is annoying: another one of those "gotchas" that sneak up on even the most experienced Maple users from time to time.
Indeed. A simpler example is this:
> f:= x -> A:
  is (f(x) > 0) assuming A > 0;
false The help page ?assuming,details says
The assuming command does not scan programs regarding the presence of assumed variables; for that purpose use assume. Consider
> f := proc(x) sqrt(a^2)+x end proc;  # a Maple procedure (program)
f := proc(x) sqrt(a^2) + x end proc
The variable a is inside the body of f; the assumption that a > 0 is not effectively used when computing f(1).
> f(1) assuming a > 0;
(a^2)^(1/2)+1
For these purposes, use assume.
So this is a design decision, not a bug. Nevertheless, it is annoying: another one of those "gotchas" that sneak up on even the most experienced Maple users from time to time.
BinarySearch works if the list it is given is sorted in lexicographic order. Note that
> sort(Dictionary, lexorder);
returns the sorted list, but doesn't sort it in-place (that only happens for sorting polynomials). You'd need to say
> Dictionary := sort(Dictionary, lexorder);
The question asks you to prove that the BinarySearch procedure as listed in the "Performing a Binary Search" section always terminates, presumably for any inputs that Maple can evaluate. The computation would not terminate if you gave BinarySearch an input whose evaluation would not terminate, e.g.
BinarySearch(Q(),w,s,f)
where
Q := proc() while true do end do end proc;
but presumably that doesn't count; it's not BinarySearch that's not terminating, it's the evaluation of its arguments. It does not ask you to prove that the result is correct. Termination with an error message (which is possible) counts as termination. Hint: perform mathematical induction on f - s, which must be a nonnegative integer or the procedure terminates right away.
To me (as a mathematician) "demonstrate" means "prove". Moreover "always" means "always", not just "in those cases I tested". When a procedure such as this fails, it's usually not in a typical case, but a very special one that you'd be unlikely to include in your test suite, so it's really good to have a proof. Maple is not much help in this, you have to use your head (I guess automatic theorem-proving software might be used, but that's really overkill here).
It's not clear exactly what you're looking for. Of course c is an upper bound for c-1, but so are lots of other things. If you want it "as tight as possible", then the only answer is the function itself. It's not true that 1 - 1/c is an upper bound for f = 1/(j*(c^j-1)), e.g. try j=1,c=2. One thing you can do is write 1/(j*(c^j-1)) = 1/j*sum(c^(-j*k),k=1..infinity) So for lower bounds you might take 1/j*sum(c^(-j*k),k=1..N) for some finite N. For upper bounds, you might take 1/j*(2*c^(-j*(N+1))+sum(c^(-j*k),k=1..N))
It's not clear exactly what you're looking for. Of course c is an upper bound for c-1, but so are lots of other things. If you want it "as tight as possible", then the only answer is the function itself. It's not true that 1 - 1/c is an upper bound for f = 1/(j*(c^j-1)), e.g. try j=1,c=2. One thing you can do is write 1/(j*(c^j-1)) = 1/j*sum(c^(-j*k),k=1..infinity) So for lower bounds you might take 1/j*sum(c^(-j*k),k=1..N) for some finite N. For upper bounds, you might take 1/j*(2*c^(-j*(N+1))+sum(c^(-j*k),k=1..N))
It's trickier to get a maximum for natural numbers. Relax the problem to real numbers and Maple can do it.
> f := 1/(j*(c^j-1)):
  maximize(f, j=1..infinity, c = 2 .. infinity, location);
1,{[{j = 1, c = 2}, 1]}
> minimize(f, j=1..infinity, c = 2 .. infinity, location);
0,{[{j = infinity}, 0], [{c = 2, j = infinity}, 0], [{c = infinity}, 0], [{j = 1, c = infinity}, 0]} So the maximum value is 1, attained at j=1,c=2, and the minimum (or more correctly infimum) is 0, attained in the limit as j -> infinity for any c or as c -> infinity for any j.
It's trickier to get a maximum for natural numbers. Relax the problem to real numbers and Maple can do it.
> f := 1/(j*(c^j-1)):
  maximize(f, j=1..infinity, c = 2 .. infinity, location);
1,{[{j = 1, c = 2}, 1]}
> minimize(f, j=1..infinity, c = 2 .. infinity, location);
0,{[{j = infinity}, 0], [{c = 2, j = infinity}, 0], [{c = infinity}, 0], [{j = 1, c = infinity}, 0]} So the maximum value is 1, attained at j=1,c=2, and the minimum (or more correctly infimum) is 0, attained in the limit as j -> infinity for any c or as c -> infinity for any j.
The 100 is arbitrary; change it, make it configurable, or remove it if you wish. It's just to avoid unpleasantly complicated results with very large exponents. Note that the same "magic number" is in `expand/sin`: try
> expand(sin(99*x));
and
> expand(sin(100*x));
"Does Maple know that that would be silly and means are obviously desired?" No, emphatically no! Never forget that Maple, despite all its power, has absolutely no intelligence. It has no idea what you want to do, and it is just doing what you tell it to do. In those cases where it does try to guess what you meant rather than what you wrote (e.g. in parts of the Standard GUI) the results are often disappointing. You have to take a look at what Means3 actually is, and work out what it does. The "curry" is just a convenient way to produce a procedure without using -> or proc. For the understanding of Means3, it's probably better to look at the direct definition.
> Means3 := () -> map((`+` @ op)/nops, args);
So here's what happens when Means3 is given a list of lists:
> Means3([[a,b],[c,d,e]]);
The "map" applies its first operand, the function (`+`@op)/nops, to each operand of the argument [[a,b],[c,d,e]], i.e. to each of the lists [a,b] and [c,d,e]. `+`@op adds the members of the list, since "op" turns the list into a sequence and `+` does the addition. "nops" takes the number of operands of the list. Thus (`+`@op)/nops adds the members of a list and divides by the number of operands. If, let's say, you wanted to divide by the number of lists, that number is "nops" of the top-level list. So you don't want that part to be mapped. You could use
> Means4 := curry(map,`+`@op)/nops;
or more directly
> Means4 := () -> map(`+`@op,args)/nops(args);
There doesn't seem to be an `expand/Re` or `expand/Im`. Defining them might help. I think this works:
> `expand/Re`:= proc(x)
   local y, p, q, n;
   y:= expand(x);
   if type(y, `+`) then
     map(Re,y)
   elif type(y, `*`) then
     p:= op(1,y); q:= subsop(1=1,y);
     Re(p)*expand(Re(q)) - Im(p)*expand(Im(q));
   elif type(y, `^`) then 
     p:= op(1,y); n:= op(2,y); 
     if type(n,posint) and n < 100 then
       add((-1)^j*binomial(n,2*j)*Re(p)^(n-2*j)*Im(p)^(2*j),
         j=0..n/2)
     elif type(n,integer) and n < 0 then
       expand(Re(p^(-n))*abs(p)^(2*n))
     else Re(y)
     end if
   else Re(y)
   end if
  end proc;
  
`expand/Im`:= proc(x)
    local y, p, q, n;
    y:= expand(x);
    if type(y, `+`) then
      map(Im,y)
    elif type(y, `*`) then
      p:= op(1,y); q:= subsop(1=1,y);
      Re(p)*expand(Im(q)) + Im(p)*expand(Re(q));
    elif type(y, `^`) then 
      p:= op(1,y); n:= op(2,y); 
      if type(n,posint) and n < 100 then
   add((-1)^j*binomial(n,2*j+1)*Re(p)^(n-2*j-1)*Im(p)^(2*j+1),
           j=0..(n-1)/2)
      elif type(n,integer) and n < 0 then
        expand(Im(p^(-n))*abs(p)^(2*n))
      else Im(y)
      end if
    else Im(y)
    end if
   end proc;
 

 > expand(Re(x+y));
Re(x)+Re(y)
> expand(Re(x*y));
Re(x)*Re(y)-Im(x)*Im(y)
> expand(Im(x^5));
5*Re(x)^4*Im(x)-10*Re(x)^2*Im(x)^3+Im(x)^5
Assuming that something is "complexcons" does not cause Maple to treat it as "complex".
> assume(x, complexcons):
  is(x, complex);
false "complexcons" is not mentioned in the help page ?property.
That would be a good question to ask your teacher.
That would be a good question to ask your teacher.
First 164 165 166 167 168 169 170 Last Page 166 of 187