Carl Love

Carl Love

28035 Reputation

25 Badges

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

MaplePrimes Activity


These are replies submitted by Carl Love

@waseem You're welcome. It's also possible to embed the betas in the plot with pointers to the curves, as in your example plot. This would require looking at the plot after a first draft is plotted so that you can decide on the placement coordinates.

Why do your command prompts keep switching between "F > " and "PW > "? I've never seen switching prompts.

@edahl Since you have Maple 16, also look up ?elementwise, which explains ~.

My guess is that will also work in Maple 16:

F:= (k::posint)-> assign([m||(1..2*k)] =~ [seq([dx||i, dy||i][], i= 1..k)]):

 

In a comment above, I forgot to say that using || is another way to guarantee that a variable is global. Using parse is similar, but not identical: It can grant you access to a top-level local from within a procedure. All of ||, cat, nprintf, and convert(..., name) are essentially the same with respect to globalness/localness.

Here's a procedure that shows 7 variations:
 

restart:

interface(warnlevel= 0):

glob:= 5:
local glob:= 9:

proc()
local
   glob:= 3,
   loc:= parse("glob"),
   x:= eval(loc),
   `code:`:= `value:`,
   L:= [
      '`code:`', 'x', 'loc', 'eval(loc)', 'glob',
      ':-glob', 'cat(``, 'glob')', '``||glob'
   ]
;
   assign('loc'=7);
   <subs(``= `\`\``, L); eval(L)>
end proc
();

Matrix([[`code:`, x, loc, loc, glob, glob, `\`\`glob`, `\`\`glob`], [`value:`, 9, 7, 7, 3, 5, glob, `3`]])

(1)

glob, :-glob;

9, 5

(2)

 


 

Download Locally_produced_globals.mw

@edahl Let's first get this working in your version of Maple, then I'll explain the code that works for you. My guess is that your Maple is older than Maple 13, which would make =~ not work. Regardless, try this, which uses zip(`=`, A, B) as an older version of what's now abbreviated as A =~ B:

restart:
F:= (k::posint)-> assign(zip(`=`, [m||(1..2*k)], [seq([dx||i, dy||i][], i= 1..k)])):
F(3), m||(1..6);

Look at these help pages: ?|| and ?zip. Actually cat is more flexible than ||. You're right that ~ is very similar to map. It can also replace zip, depending on the context.

@vv Okay, yes, I see that. The answer only applies to the OP's specific context. It's what I call an ad hoc answer. And I'm not saying that ad hoc answers are a bad thing! But I think that it's clear in this case that it doesn't really address the OP's overall Question.

@vv Yes, that works for that simple example, but it is awkward. If the procedure's author needs explicit access to the bound variable (which would be true in the majority of practical cases), it requires subtle "surgery" of f and/or r to get to the variable without accidentally evaluating it. Plus, there are numerous benefits of arguments being evaluated before they are passed.

Consider what you would need to do in your example if you were writing a simple alternative to plot rather than simply passing the arguments on to plot.

@vv No: Ignoring the restart for the moment, that x is not necessarily global either. It could also be lexical, module local, module export, or top-level local. There are two ways to guarantee that a variable is global: declare it global or prefix it with unary :-.

@Adam Ledger The issue that leads to the error is that the bound (or "dummy") variables of integration are being considered by NonlinearFit as if they were model parameters to be fitted. Hence it tries substituting numeric values for them. This issue is easy to fix by turning the model into an arrow procedure whose procedure parameters are the independent variable, x, followed by the true model parameters, beta and `&Delta;A`. This removes the error, but actually getting an answer is another matter.

@nm I'm sorry, but you've mistaken my ad hoc workaround Answer above as being more general than I intended. By ad hoc, I mean that it was intended to apply to the specific plot that you originally posted, on which the original scale for all three axes was 0..10. It should be obvious that that particular 0.4-factor adjustment cannot work for a general plot. And by workaround, I mean something that's meant to bypass a shortcoming or bug of Maple until better library code is written; I don't mean something that's intended to give Maple functionality equivalent to Mathematica in some area.

It'd be fairly easy for me to write a procedure to rescale the lengths of all the axes of a general plot to visually conform to any "box ratios" that you wanted. But rescaling the tickmarks of an unseen Maple plot is hellishly complex because a Maple programmer has no access to the tickmarks of the original plot when they are generated by the plot renderer in the GUI, which is the case for the vast majority of plots. In other words, a plot that a user sees on their screen has more information, more detail, than a Maple programmer has access to.

This is a shortcoming of Maple. Mathematica handles it much better. You'll get no argument from me about that.

@Carl Love You also asked if there was a way that was even more efficient than your first. Yes:

nFrames:= 10:
plots:-display(
   [seq(plot(sin(i*t), t= -2*Pi..2*Pi), i= 0..nFrames-1)],
   insequence
);

There are two separate simplifications that I've done: I replaced for with seq, and I eliminated the temporary variables frames and w (which become garbage that needs to be collected). When creating sequences, lists, or sets iteratively, for can be replaced by seq whenever

  1. the element being created doesn't depend on any of the previous elements, and
  2. the condition for ending the sequence doesn't depend on any of the previous elements.

The efficiency difference between your first and second methods is huge for large nFrames. The additional efficiency achieved by using my variation above is tiny by comparison.

@Adam Ledger Yes, your observation about the implication of the coprimality of j and k is correct. But even thinking about the simple concept of coprimality is already getting more complicated than is necessary for the problem.

@vv Yes, of course, his algorithm is fine (and perhaps asymptotically the best). It's only its implementation in Maple that's bad. In Maple, one shouldn't use sqrt on integers with a huge number of divisors, use is on large-number exact inequalities, or use arrow expressions containing function calls that are constant with respect to the arrow's parameters (unless one is sure that there's a remember table in effect). The first two of these are Maple-specific pitfalls; the third is something that a competent programmer in any language should foresee (though it's easy in Maple to overlook the fact that an arrow expression is a procedure like any other).

I was quite surprised at how brutal on my system and unstoppable his function was when applied to my data. And I tried several times, each time using smaller and fewer data.

@Carl Love 

Here are the two algorithms that I was talking about, plus Heinz's:
 

restart:

I want to measure the times of the algorithms without measuring the time required by numtheory:-divisors. Since its time is common to both, it's irrelevant to comparing these two algorithms. To do this, I use a remember table.

Divisors:= proc(n::posint)
option remember;
   numtheory:-divisors(n)
end proc:

Algorithm using sort:

MidDivisor_sort:= (n::posint)-> (D-> D[1+iquo(nops(D),2)])(sort([Divisors(n)[]])):

Algorithm using select:

MidDivisor_select:= (n::posint)-> min(select(`>`, Divisors(n), isqrt(n))):

Heinz's algorithm is the same as the second, but his implementation of it is horrible because he uses the highly symbolic and very slow commands is and sqrt (without evalf).

Heinz:= n-> min(select(d-> is(d=n or d>sqrt(n)), Divisors(n))):

Generate some random test data: A list of numbers that have a lot of divisors.

E:= rand(0..19):

N:= ['rand()*mul([2, 3, 5, 7]^~['E()'$4])' $ 64]:

Load the remember table:

Divisors~(N):

Let them run!

gc(); L1:= CodeTools:-Usage([MidDivisor_sort~(N), gc()]):

memory used=71.81MiB, alloc change=0 bytes, cpu time=1.36s, real time=1.25s, gc time=625.00ms

 

gc(); L2:= CodeTools:-Usage([MidDivisor_select~(N), gc()]):

memory used=463.00MiB, alloc change=0 bytes, cpu time=8.48s, real time=5.62s, gc time=4.78s

 

Warning: Do not try to test Heinz's code on this data! You will crash Maple. His code is only good for baby numbers.

 

Verify that the results are the same:

evalb(L1 = L2);

true

(1)

 

Download MidDivisor.mw

Now, that stuff about asymptotic time complexity: Let ND be the number of divisors of n. It's clear that the select does a linear scan of length ND, and the min does a linear scan of length ND/2. The isqrt is sublinear (that's not so clear, but it's clear that it's done only once for each n). So the second algorithm is O(ND). Other than hand, the first algorithm does a sort, so it must be at least O(ND*log(ND)). That's why I know that it's guaranteed that there's some n (indeed, a whole infinitude of them) such that the select algorithm is faster than the sort algorithm. But those n are likely incredibly large, since Maple's sort is very fast.

Some readers may ask Why use sort at all? Aren't sets of integers sorted always already in Maple? Yes, that's certainly true for word-sized integers at this point, and perhaps all integers. But it's bad programming practice to rely on it. So, that's a problem (admittedly, a very small problem), with Tom's "break" algorithm.

@Gabriel samaila 

It's easy to include extra boundary values with exactly one new parameter each in the dsolve command (only for a BVP). The command will solve these for you, filling in the numeric values of the parameters. Since the skin friction = C__f and Nussel = Nu are defined this way (Eq. 14), I included them and produced Tables 1-3. For Tables 2 and 3, I got a perfect match with the paper down to the last digit. My Table 1 is incorrect because they only specify 4 of the 8 required parameters. I couldn't find what values they used for the others! Once you find these 4 values (by email maybe), you can easily fill them into my code. Here's the updated worksheet. It includes everything from the previous worksheet also, so you might as well overwrite your existing copy.

nanofluid_BVP.mw

First 334 335 336 337 338 339 340 Last Page 336 of 708