Carl Love

Carl Love

28035 Reputation

25 Badges

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

MaplePrimes Activity


These are answers submitted by Carl Love

You also mentioned postfix notation. The output of InertForm:-Parse can be put into postfix notation with this procedure:

#Only intended to be used on InertForm output 
Postfix:= (f::function)->
   sprintf(
      "%A",
      evalindets(
         f, function, 
         f-> cat(nprintf("(%Q)", op(f)), nprintf("%A", substring(op(0,f), 2..)))
      )
   )
:

Your example:

Postfix(InertForm:-Parse("x+(y^(2+x)-4)/3"));

         "(x, (((y, (2, x)+)^, -4)+, 3)/)+"

Unlike the prefix output of InertForm:-Parse, the string output of Postfix has no inherent meaning to Maple, and it would take significant effort to write a procedure to automatically evaluate it.

As in the prefix form, the subtraction is handled as the addition of -4. The -4 itself is an integral operand; it is not the operand 4 acted on by an unary negation operator.

Here's one way with a single plot command. You can make many fine tunings of the ranges to see exactly the parts that you want.

eps:= .2:
x0:= Pi/4:
tan_line:= proc(f,x0) local x; unapply(D(f)(x0)*(x-x0)+f(x0), x) end proc:
plot(
   [tan, tan_line(tan, x0), arctan, tan_line(arctan, tan(x0))], 
   0..Pi/2-eps, 
   scaling= constrained, thickness= [2,0,2,0], view= [DEFAULT, -1..2]
);

 

We'll maintain two markers for the list, which I call lo and hi. Think of them as doing the same thing that your left hand does when you look up something in a paper dictionary: They keep track of the part that has yet to be searched. Then at each step, we examine the middle entry between lo and hi. If it's what we're looking for, then we're done. Otherwise, we can move one of the markers to the middle, thereby reducing the part that remains to be searched by a factor of a half.

The code below assumes 1) that the input list L is sorted with respect to the standard less-than operator `<`, 2) that the target x can be meaningfully compared via `<` to any entry of L, and 3) that if x is an entry, then it's an identical match as can determined by simple `=`. It'll be quite easy later to relax these restrictions.

BinarySearch:= proc(L::list, x)
local hi:= nops(L), lo:= 1, mid:= iquo(hi+lo, 2);
   while lo < hi do
      if x = L[mid] then return mid end if;
      if x < L[mid] then hi:= mid-1 else lo:= mid+1 end if;
      mid:= iquo(hi+lo, 2)
   end do;
   if mid <> 0 and x = L[mid] then mid end if
end proc:

Note that the second-to-last line could be written

if mid <> 0 and x = L[mid] then mid else NULL end if

However, there's never a need to write else NULL in Maple (or I believe in other Algol-based languages). If an if statement has no else clause, then it's assumed that it's else NULL.

Something like the above procedure is already implemented as ListTools:-BinarySearch. I thought that it'd be instructive for you to see the "bare bones" of this fundamental and very important algorithm.

Change every variable of the form A[b] to A__b. Note that there are two underscores. They will still display as subscripted. Using A[b] is unreliable because the meaning of this expression is not independent of A and b. On the other hand, A__b is totally independent from A and b.

If the solve still doesn't work after you do this, repost the newly subscripted expressions as a Reply to this Answer.

There are many ways to do those things. The commands that I show here are not the shortest ways, but I think that they are the best ways to learn first:

S:= seq(k, k= -10..20);
[S];
S:= seq(k, k= 115..231, 2);
[S];

 

The command unapply is the most general way to turn an expression into a function:

f:= unapply(Statistics:-PolynomialFit(4, X, Y, x), x);

Defining a function via

f(x):= ...

is unreliable, and clunky at best.

If an expression E contains the variable x, and E evaluates to itself, then you can do

f:= x-> E;

You must use exact arithmetic, not decimals, like this:

restart:
with(geom3d):
line(l1, [point(p1, [15, 6, 34/10]), vector([-4, 12, 3/10])]):
line(l2, [point(p2, [-17, 54, 32/10]), vector([6, -6, 2/10])]):
intersection(p, l1, l2):
coordinates(p);

 

The following formula is usually the first general formula for infinite summation that most of us learn, so it's likely that you're familiar with it:

sum(a*r^n, n= 0..infinity) assuming abs(r) < 1;

      -a/(r - 1)

Your first sum is clearly equivalent to sum(4^n, n= 1..infinity). If we ignore the abs(r) < 1 part and apply the above formula anyway, we get -4/(4 - 1) = -4/3. This is called "formal" summation. I don't understand why anyone would want this result, but I guess that some mathematicians have their reasons for wanting it since it has a name. Here's what the help page ?evalf,sum has to say about it:

"In the case of infinite sums, Levin's u-transform is used, which has the additional effect that sums that formally diverge may return a result that can be interpreted as evaluation of the analytic extension of the series for the sum (see the examples below).

"This behavior can be controlled through the use of the formal option or the _EnvFormal environment variable. If this variable is assigned the value false, or formal=false is specified, then this command will apply some (numeric) convergence tests to determine if the infinite sum in question is convergent, divergent, or otherwise non-convergent."

For your second sum, Maple doesn't know any way to simplify floor(5^n/4).

 

All you need to do is

:-subs((`=`@op)~(subs), h);

This is using the subs command. Since you apparently also have a local variable named subs, I need to use :-subs to refer to the command. If you change the name of the local variable (which I recommend that you do), then you may change :-subs to subs.

This will work only if the floating-point constants in subs exactly match those in h. If they're not exact matches, then we may need to chop off a few digits of precision to force them to match exactly.

Maple's default notion of equality, as expressed by evalb(x = y), is identity. That is, two objects are considered equal iff they are in fact identically the same object, stored at the same address. That is, if they're considered equal, they're actually only one object with two names, x and y. Two matrices that happen to have identical entries may be stored at different addresses and thus they'd be considered not equal under the default notion of equality.

You don't need to use that default notion of equality; there are many ways that Maple has available to determine equality. The command LinearAlgebra:-Equal will say that two matrices are equal if their entries are equal, even if they're stored at different addresses. The command ListTools:-MakeUnique(L), with no other arguments, is using the default equality. You should change that to ListTools:-MakeUnique(L, LinearAlgebra:-Equal).

When something is copied by copy-and-paste to another worksheet, only the superficial structure is copied, not the addresses. I guess that in that process matrices that are obstensibly equal end up stored at the same address. I wouldn't rely on this process.

None of the above is true for lists or sets with numeric entries: If they're obstensibly equal, then they're stored at the same address and Maple will always say that they're equal. To maintain that, Maple needs to recognize when a newly created list or set matches one that already exists. This is part of automatic simplification.

Because of all of the above, if you have a program that creates a huge number of small matrices of exact numbers, and some of them are equal, then it's sometimes better to create them as lists of lists (also called listlists) rather than as explicit matrices.

Do

subs(max(L)= 0, L);

 

Do

solve({f(x) = y, x < x__1}, {x}, parametric, real);

This is currently only implemented for polynomial f. What you get back from that solve is a deeply nested piecewise expression which you'll need to deconstruct. For the present case, that can be done by

op([2,1,1,2], %);

 

It's very easy.

1. Remove from your code the line t:= 0.

2. Change the final plot command to

animate(
   fieldplot3d, 
   [[E0[x], E0[y], E0[z]], x = -.3 .. .3, y = -.3 .. .3, z = -10 .. 10, 
    grid = [10, 10, 10], arrows = SLIM, color = black
   ], t= 0..10
);

(The arguments in the outermost pair of square brackets are exactly the same arguments as your original fieldplot3d command.).

3. Re-execute the entire worksheet, including the restart.

This is just to answer your secondary question about the gridlines. I haven't yet figured out how to solve your main problem.

You can make the gridlines invisible by including option style= patchnogrid. The grid will still be in effect computationally, and the option grid= [m,n] will be effective; you just won't see the gridlines.

However, as you've already noticed, enlarging the grid won't solve your problem! It'll just make the computation lengthier and the worksheet larger and slower to load, scroll, and autosave.

Here is the code translated into Maple. I strove to maintain the character of the code (including all the variable names) while avoiding the serious shortcomings of Fortran. Despite what MacDude said, this code is not at all slow. Indeed, it's 5 times faster than RandomTools:-Generate and 6 times faster than rand(0. .. 1.), although it's 3 times slower than Statistics:-Sample.

ran1:= module()
export idum, iv, iy:= 0;
local
   ModuleLoad:= proc()
   option hfloat;
   local PARAMETER;
      Digits:= trunc(evalhf(Digits));
      PARAMETER:= 
         [
            [AM= 1./IM, NDIV= 1+iquo(IM-1, NTAB), RNMX= evalhf(1-DBL_EPSILON)],
            [IA= 16807, IM= 2147483647, NTAB= 32]
         ]
      ;
      (ModuleApply, Init):= subs(PARAMETER[], eval~([ModuleApply, Init]))[]
   end proc,

   Init:= proc(seed)
   local j;
      iv:= Vector(NTAB, datatype= integer[4]);
      idum:= max(-seed, 1);
      for j from NTAB+8 to 1 by -1 do
         idum:= irem(IA*idum, IM);
         if j <= NTAB then iv[j]:= idum end if
      end do;
      iy:= iv[1];
   end proc,

   ModuleApply:= proc(seed::integer:= 0)
   option hfloat;
   local j;
      Digits:= trunc(evalhf(Digits));
      if seed < 0 or iy = 0 then Init(seed) end if;
      idum:= irem(IA*idum, IM);
      j:= 1 + iquo(iy, NDIV);
      iy:= iv[j];
      iv[j]:= idum;
      min(AM*iy, RNMX)
   end proc
;
   ModuleLoad()
end module:

To use it, first call it with a negative integer argument to initialize it, for example, ran1(-42). After that, no argument is needed, and any nonnegative integer argument is ignored. Initializing is optional; simply starting with ran1() is equivalent to ran1(-1). A histogram of a sample of 10000 shows a reasonably uniform distribution. This can be done like this:

N:= 10000:
ran1(-42): A:= Vector(['ran1()' $ N], datatype= float[8]):
Statistics:-Histogram(A, frequencyscale= absolute);

For comparison, the other methods that I used are

B:= Vector(
   RandomTools:-Generate(list(float(range= 0. .. 1., method= uniform), N)),
   datatype= float[8]
):
C:= Statistics:-Sample(Uniform(0,1), N):
R:= rand(0. .. 1.); E:= Vector(['R()' $ N], datatype= float[8]);

 

First 179 180 181 182 183 184 185 Last Page 181 of 395