Carl Love

Carl Love

28025 Reputation

25 Badges

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

MaplePrimes Activity


These are answers submitted by Carl Love

You have numerous syntax errors and some other problems. The specific problem that caused your error message is irrelevant. I am reluctant to list all the errors because there are so many and because some of them interact with some others in ways that make them difficult to describe individually. So first I'll post my corrected version of the code, then I'll make some comments.

B:= 10;
A:= Array(1..B, 0);

#b is in your code, but you never gave it a value.
b:= 2;
#You'll get more meaningful results by using larger primes.
p:= 2^20;

for i from 1 to B do
     p:= nextprime(p); #Not nextprime(i)
     a:= numtheory:-primroot(p);
     #Garbage collecting leads to more accurate timings.
     gc();
     A[i]:= A[i]+
         CodeTools:-Usage(
               numtheory:-mlog(b,a,p, method= indcalc),
               output= cputime, quiet, iterations= 2^12
         )
end do;

A;

Additional comments:

1. Remember to use := for assignment statements rather than simply =
2. Commands in packages need the package prefix, i.e., numtheory:-primroot rather than simply primroot.
3. convert(..., decimal) is meaningless in this context: The values returned by Usage are already decimal.
4. When timing a small operation, you need to use the iterations option to get meaningful results. This is because the resolution of Maple's clock is much, much larger than the resolution of your CPU's clock.
5. I don't see any point in specifying output= [cputime, output] since you're discarding the output.

To get {-2,3}, use

eval({x,y}, result);

If you use sets like that (they're sets because they're in curly braces), then you cannot rely on the first element corresponding to x and the second corresponding to y. Indeed, if the values of x and y are the same, then your set will only have one element. For these reasons, you should use lists instead of sets, like this:

eval([x,y], result);

The $ (unlike seq) can work symbolically, i.e., for symbolic values of i. And diff can work with this information to produce derivatives of arbitrary order. (Of course, diff can only do this for somewhat simple functions.) Observe the output of your first command:

diff(x^7, x$i);

This expression gives a valid derivative for any i, including i = 0. In your first example, this is the expression that is passed to seq, which then simply plugs in the values of i.

The command seq has "special evaluation rules" similar to the first parameter being declared with uneval (see ?uneval) . (These rules also apply to add and mul.) You are correct that these rules are not described at ?seq. These rules mean that in your second example, the unevaluated expression diff(x^7, x$i) is passed to seq. Evaluating this expression at i=0 causes an error because the expression becomes diff(x^7, NULL)i.e., nothing is after the comma. This can be avoided by using diff(x^7, [x$i]), which is valid for any i, even if the [ ] are empty.

 

You have a classic off-by-one error. In addition to the problem pointed out by sazroberson of not propagating in the other arrays, you are also not propagating to the next value of i.

Change the lines

S[i]:= S[i-1], etc. to

S[i+1]:= S[i], etc.

In the long if - elif block, change each line of the form

S[i]:= S[i]+1 to

S[i+1]:= S[i]+1.

Remove the if statement that prevents the execution of this code for i=0.

Jakub,

I have finished the project including extensive research of your course handouts from your professor's website (http://www.kosiorowski.edu.pl/wp-content/uploads/2014/10/Ia-NumMet-W-S-1-Error-theory.pdf) and a complete-from-scratch rewrite of your code including individually checking for zero denominators for each method (so that the procedure will perform all applicable methods even if some are inapplicable). I extended the code so that it works for functions of any number of variables (not just x, y, z) while at the same time vastly simplifying it.



Write the procedure of the name INVERROR, whose entries are:

• 

function of three variables,

• 

approximate values of its variables,

• 

upper bound for value of "f,"

• 

if some method cannot be applied, the information about it should be noted.

 

The procedure should calculate admissible errors for each variable, by three different methods in the inverse problem of error theory.

The exemplary output should be:

=====================================

equal upper bounds method:

e[x] = e[y] and e[y] = e[z] and e[z] = 0.2e-2

equal influence rule:

e[x] = .3, e[y] = 0.2e-2, e[z] = 0.1e-1

equal mesurement method:

e[x] = 0.1e-1, e[y] = 0.5e-2, e[z] = 0.2e-1

=====================================

It may be also in tabluar/vector form. The decision is yours.

 

 

The standard instructions for summation and derivatives do not require any special package.

 

 

errorf:= (f::procedure, X::list(float))->
     trunc(
          10.^Digits*
          evalf(add(abs(D[_](f)(X[])*(round(X[_])-X[_])), _= 1..nops([op(1,eval(f))])))
      )/10.^Digits
;     

proc (f::procedure, X::(list(float))) options operator, arrow; trunc(10.^Digits*evalf(add(abs((D[_](f))(X[])*(round(X[_])-X[_])), _ = 1 .. nops([op(1, eval(f))]))))/10.^Digits end proc

(1)

func := proc (x, y, z) options operator, arrow; 2/x+3/y+4/z end proc;

proc (x, y, z) options operator, arrow; 2/x+3/y+4/z end proc

(2)

Delta[f] := errorf(func, [2.01, 3.11, 2.1]);

.1297720743

(3)

INVERROR:= proc(f::procedure, x::list(float), E::float)
local
     n:= nops([op(1,eval(f))]), #arity of f
     d:= evalf(abs~([seq(D[_](f)(x[]), _= 1..n)])), #abs~grad(f(x))
     X:= abs~(x),
     S:= `+`(d[]) #1-norm of grad(f(x))
;
     if fnormal(S)=0 then
          error "Norm of gradient is 0. Cannot proceed with any method."
     end if;
 
     printf("\nequal upper bounds method:\n%g", E/S);

     if `*`(fnormal~(d)[]) = 0 then
          printf("\nGradient has a zero component. Cannot use equal influence rule.")
     else
          printf("\nequal influence rule:\n%g", <(E/n/~d)[]>)
     end if;

     S:= `+`((d*~X)[]);
     if fnormal(S)=0 then
          printf("\nCannot use equal measurement method due to zero denominator.\n")
     else
          printf("\nequal measurement method:\n%g\n", <(X*~E/~S)[]>)
     end if

end proc:

INVERROR(func, [2.01, 3.11, 2.1], Delta[f]);


equal upper bounds method:
0.0757909
equal influence rule:
0.087382 0.139463 0.0476912
equal measurement method:
0.0674984 0.104438 0.0705207

 

 



Download INVERROR.mw

 

The expression seq(a[i_j], i= 1..3) makes no sense. I don't just mean that it makes no sense to Maple; I mean that it makes no sense at all. For one thing, you have no iteration over j. And even if you did iterate over j, you would then have subscripts on the integers i. And what would that mean?

Something that could possibly make sense would be

seq(a[i[j]], j= 1..3)

or

seq(a[i||j], j= 1..3)

or

seq(a[i_||j], j= 1..3).

In each case, the iteration is over j. Perhaps that is what you meant.

Your problem is caused by you typing an extra space after cos. You have entered the forcing function as

u*cos (omega[g]*tau)

which is interpretted by the odious 2d input parser as if you had typed

u*cos*omega[g]*tau.

You need to change it to

u*cos(omega[g]*tau).

It's only a difference of one space. 

This problem will be avoided if you use the 1d input (which ignores extra spaces between a name and a punctuation mark, like most reasonable computer languages), like this:

(Display of uploaded worksheets is broken. But you can download my worksheet below.)

Download ODE.mw

I recommend that you do not use .jpg for mathematical plots: it makes lines and text blurry. So, it'll be .png.

The plotsetup command can be used to programmatically redirect plot output to a file. I find this easier and more precise than using mouse controls to export a high-quality plot (although I do use the mouse controls to export most of the regular-quality plots that I post here). Working with high-resolution plots in a worksheet (either Standard or Classic) will make the interface excruciatingly slow. Of course, you'll probably want to look at the plot in the worksheet while you're perfecting it. While you're doing that, avoid scrolling the worksheet, and never have two such plots in the same worksheet.

plotsetup(png, plotoutput= "myplot.png", plotoptions= "width=1920,height=1080");

After issuing the above command, all plotting-command output will go to the file. To turn this off, use plotsetup(default). Notice that I used high-resolution specifications for the width and height. There is also a tranparency option that can be set to a number between 0 and 1 inclusive.

There's little point in export at high resolution if you haven't computed enough points in your plot. So, use the plotting-command options such as numpoints and grid to raise the number of computed points.

 

The reason that it's taking so long is that your inner integrals are symbolic, and Maple is not finishing that symbolic integration. Maple can do your innermost integral symbolically in a few seconds. The result is about three screens long. The next layer out takes longer; it may be the one that doesn't finish.

For the vast majority of Maple commands (procedures), the arguments are evaluated before being passed. For example, if your call were simplified to

int(int(f(x,y), x= 0..g(y)), y= 0..b, numeric);

that inner integral would be performed symbolically before the numeric integration is even started.

There's no point in trying numeric integration when you have symbolic parameters. You have k, l, a, and b.

Maple has an alternate simplified notation for multiple integrals that will help you avoid the problem of premature evaluation of inner integrals, and also vastly simplify the parentheses needed for your four-deep integral. This notation works for both numeric and symbolic integrals. In the alternate notation, my integral above becomes

int(f(x,y), [x= 0..g(y), y= 0..b], numeric);

 

Because Vector is an active procedure as well as a type and metatype, the procedure call Vector(Element) needs to be prevented. If you want to do this and also use TypeTools:-Exists, then you need two pairs of unevaluation quotes on Vector:

TypeTools:-AddType(ExpandedLine, ''Vector''('Element'));

(That's not double quotes; it's two sets of single quotes.) I can't tell you a concrete rule by which I know to use two sets of quotes; however, I've tested it, and it works.

Unlike arrays, two lists L1 and L2 can be checked for equality as a whole, i.e., without needing to do it elementwise:

if L1=L2 then "They're equal." else "They're not equal." end if;

You asked a very important question that perplexes many new Maple programmers. The best way to create a list element by element when you do not have foreknowledge of the final number of elements is to temporarily store the elements in a Maple hash table and then convert that table to a list when you're done. Like this:

Base3:= proc(n::nonnegint)
local r, R:= table(), k, q:= n;
     for k while q > 0 do
          q:= iquo(q, 3, 'r');
          R[k]:= r
     end do;
     `if`(n=0, [0], convert(R, list))
end proc:

You can do the same thing with a dynamically sized rtable. The coding is almost identical, and, as far as I can tell, it is just as efficient:

Base3:= proc(n::nonnegint)
local r, R:= Vector(1), k, q:= n;
     for k while q > 0 do
          q:= iquo(q, 3, 'r');
          R(k):= r
     end do;
     `if`(n=0, [0], convert(R, list))
end proc:

In Maple, a list cannot be initialized; there would be no point since a list cannot be modified at all. (Any examples that you may have seen of lists being modified are faked by the interpreter and are highly inefficient.) A list can be created with its final (and only) entries by

mylist:= [seq(sumsquare(k), k= 1..n)];

An array (or Array) is different from a list; it can be initialized and modified. 

The following procedure uses StringTools:-RegSplit to achieve what you want. You said that you do not need the positions; however, my algorithm necessarily generates the positions, so I thought that I might as well return them also.

RegMatches:= proc(
     P::string, #Regular expression
     T::string  #Text to search
)
uses ST= StringTools;
local
     S:= [ST:-RegSplit(P,T)],
     s,           #one result of above
     p:= 0,       #current position in T
     R:= table(), #return
     m            #a match
;
     for s in S[1..-2] do
          p:= p+length(s);
          ST:-RegMatch(P, T[p+1..-1], 'm');
          R[p+1]:= m;
          p:= p+length(m)
     end do;
     eval(R)
end proc:

Your example:

T:= "variable %1 needs to be of the form %3+2.9 "
    "in order to use routine %2 to find the fizturl":

P:= "%[0-9]+":

RegMatches(P,T);



Also, before you go and re-invent the wheel, check if StringTools:-FormatMessage will do what you need.

Here's another way, not necessarily better, using functional-programming style and, naturally, LinearAlgebra:-RandomMatrix.

P:= (n::posint, m::posint)->
     (x-> (d-> `if`(d[1]=d[-1], x, ``))(convert(x, base, 10)))~
          (LinearAlgebra:-RandomMatrix(n,m, generator= rand(100..999))):

P(10,10);

First 277 278 279 280 281 282 283 Last Page 279 of 395