acer

32328 Reputation

29 Badges

19 years, 318 days
Ontario, Canada

Social Networks and Content at Maplesoft.com

MaplePrimes Activity


These are answers submitted by acer

It's easy enough to print a single float using to a customized format. That's what printf does. Note that one of the drawbacks of fixed-digit notational printing is that it can hide trailing digit information. You can work around that, using Digits say to control the fixed format width as below (or even more dynamically also using the length of trailing nonzero digits, which I don't show here).

> restart:

> 1/1e7;
                                      -7
                        1.000000000 10  

> printf("%.10f\n", 1/1e7);
0.0000001000

> Digits:=20:

> printf("%.10f\n", 1/1e7);
0.0000001000

> printf(cat("%.",Digits,"f\n"), 1/1e7);
0.00000010000000000000

It gets harder if you want to customize how floats get printed as they appear in expressions. This does not seem to be configurable with a procedure like `print/float` (or similar) as an extension. And the various Standard GUI otpions for configuring digits-elision, etc, don't seem to cover your situation. So the simple answer to what you're asking might be no, if you want the effect for whole expressions and not just simple floats or collections of floats.

For expressions which contain floats, a solution involving just printing (and artefacts of printing only) would be nice, since then the displayed result could still be used directly in any subsequent calculation.

All I can think of right now is actual substitution into expressions, ie. replacing them with names that get printed closer to what you've requested. If you convert the floats in the expression G below to names, then the numeric quantity can be recoved later using `parse`, and so used in subsequent computation.

Unfortunately, the float-name objects get displayed in the Standard GUI in italics (so, not quite as nice as you see below). Also, they don't necessarily appear in front, as you'd normally expect from numeric coefficients.

> restart:

> convert(sprintf("%.10f", 1/1e7),`name`);

                             0.0000001000

> parse(%);

                                      -7
                              1.000 10  

> G:=sin(y*1e-7)*exp(5e-7*x);

                        /    -7  \    /    -7  \
                     sin\1 10   y/ exp\5 10   x/

> conv:=proc(x)
>    convert(sprintf(cat("%.",Digits,"f"), x),`name`);
> end proc:

> subsindets(G,float,conv);

               sin(y 0.0000001000) exp(x 0.0000005000)

> Digits:=20:

> subsindets(G,float,conv);

     sin(y 0.00000010000000000000) exp(x 0.00000050000000000000)

> subsindets(%,name,parse);

          /                  -7  \    /                  -7  \
       sin\1.0000000000000 10   y/ exp\5.0000000000000 10   x/

Another variation of the above is to use something like atomic identifiers (or TypeMK or whatever undocumented thing one wants to call it...). In this form, the printing in the GUI is in an upright font, not italic. But now there is no easy recovery of the numeric object, that I know of, so use in subsequent computation is problematic.

And the numeric-names still don't appear in front as coefficients.

> restart:

> G:=sin(y*1e-7)*exp(5e-7*x);

                        /    -7  \    /    -7  \
                     sin\1 10   y/ exp\5 10   x/

> conv:=proc(x)
>    cat(`#mo(`,sprintf("%.10f",x),`)`);
> end proc:

> subsindets(G,float,conv);

                  sin(y 0.0000001000) exp(x 0.0000005000)

> Digits:=20:

> conv:=proc(x)
>    cat(`#mo(`,sprintf(cat("%.",Digits,"f"),x),`)`);
> end proc:

> subsindets(G,float,conv);

         sin(y 0.00000010000000000000) exp(x 0.00000050000000000000)

acer

The difference is that in the case of your example 2 the argument to sqrt is first computed as a single float. That causes the `sqrt` command to follow that path of computation appropriate for that input.

> restart:
> trace(sqrt):

> evalf(sqrt(3.0*(1/4)), 5);

execute sqrt, args = .7500000000
{--> enter sqrt, args = .7500000000
                            0.86603
<-- exit sqrt (now at top level) = .86603}
                            0.86603

In your example 3, the `sqrt` command evaluates symbolically, up front and before `evalf` gets in on the action. And what sqrt does is pull out the 1/2 factor. This turns it into your example 4.

> restart:
> trace(sqrt):

> evalf(sqrt(3*(1/4)), 5);

execute sqrt, args = 3/4
{--> enter sqrt, args = 3/4
execute sqrt, args = 12
{--> enter sqrt, args = 12
                               3
                               1
                               1
                               12
                               6
                               2
                               2
                               1
                               3
                               2
                               1
                               1
                               1
                               1
                               3
<-- exit sqrt (now in sqrt) = 2*3^(1/2)}
                            1  (1/2)
                            - 3     
                            2       
<-- exit sqrt (now at top level) = (1/2)*3^(1/2)}
                            0.86605

And your example 1 gets handled not much differently from how example 4 gets handled.

Let's address your highly sensible question:

    "What would be the right command to get an accurate rounded result for
     1/2)*sqrt(3)?"

In order to answer that properly we'll need a little bit of knowledge about Maple's "model of floating-point computation", ie. its (stated or unstated) rules and behavior.

Digits=5 means that Maple's working precision is 5. It doesn't mean that 5 digits of accuracy are promised for floating-point computation of general compound expressions. There is no environment variable which relates to accuracy in the way that Digits relates to the working precision.

So by reducing Digits to 5 (or somewhat equivalently by calling evalf[5] or evalf with 5 as second argument) you are reducing the working precision and making results less accurate that usual. You are not at all ensuring that the result are accurate to 5 digits. Indeed, you are making that quite less likely to occur.

For your very simple example, you can display 5 accurate digits of result by allowing Maple to compute an intermediate result at a higher working precision (even the default Digits=10 suffices here) and simultanteously controlling how that intermediate result gets printed. Here are two ways to get that, done in the Standard GUI as 1D input in a Worksheet,

restart:
interface(displayprecision=5):
evalf( 1/2*sqrt(3) );
                            0.86603
restart:
ans:=evalf( 1/2*sqrt(3) ):
evalf[5](ans);
                            0.86603

Interestingly, that first result above is only being printed as 0.86603 to the display. Maple's engine still knows that its value is actually 0.8660254040 for subsequent computation. (True also for cut'n'paste outside Maple.) If you don't like that, then the second result above is stored internally just as it shows.

I hope that helps.

Some people might now ask, how can you know how high to raise Digits, to ensure that there are enough correct digits in the result to display? One answer to that involves the `shake` command. ...and I'm overdue for finishing a promised Post on that.

acer

It looks like a bug in either the 2D Math parser or the Standard GUI.

Here's a simpler example to reproduce.

Worksheet (not Document), 2D Math input mode, a single execution group:

One the first line,

restart:

On the next line (after <shift>-<enter>), a Matrix with say numerical entries entered using the Matrix palette.

M := Matrix([[1,2],[3,4]])

Then <enter>. The above displays nonsense output that looks like M:=_rtable[5163856]. That appears to be a bogus handle ("handles" being what the GUI uses internally to refer to rtables such as Matrices in output, when talking to the kernel). If one subsequently queries M[1,1], say, a value is not obtained (let alone the correct value).

I will submit this as a bug report.

acer

Create the container Matrix like one of the following (depending whether symmetric),

M:=Matrix(47008,47008,storage=sparse,datatype=float[8]):

MS:=Matrix(47008,47008,shape=symmetric,storage=sparse,datatype=float[8]):

That will create a Matrix whose data is stored in three contiguous arrays in memory. You shouldn't need to access these. And you can insert entries as you go, with Maple automatically adjusting the size of the internal storage. (Actually, it adds a little buffer whenever you insert past the current amount of stored space. More details that you don't normally need to know.)

Now you can add entries. If you want, you can also query how many entries are stored, allocated, etc.

> rtable_num_elems(MS,'Stored');
0

> rtable_num_elems(MS,'Allocated');
0

> MS[4,3]:=3:
> MS[3,4];
3.0

> rtable_num_elems(MS,'Stored');
2

> rtable_num_elems(MS,'Allocated');
10

> for i from 1 to 10 do
> MS[i,i+3]:=sin(1.0*i):
> end do:

> rtable_num_elems(MS,'Stored');
22

>rtable_num_elems(MS,'Allocated');
30

So you can then write regular Maple code to assign entries into the Matrix. You can also call LinearSolve on that Matrix and a datatype=float[8] (non-sparse!) Vector as the right-hand-side. That should automatically invoke an appropriate sparse linear solver (NAG's f11daf, f11dcf). See here for an example showing that.

Note that datatype=float[8] is key. Without it the storage=sparse option to the Matrix constructor will produce another kind of structure internally (a sparse table, internally) which is not suitable for those sparse linear solvers.

It's likely a bad idea to try and form a set of the indexed entries (like suggested in this answer), as the set itself will likely be comparable or maybe even much larger than the sparse float[8] Matrix itself. It'll likely be important to avoid storing the data in any form except the final target sparse float[8] container Matrix (even if only temporarily). If you run into problems with that, maybe ask again (with same code posted?) Hope that makes sense.

acer

Good news is that regular Maple already has (another, completely separate) copy of several of these f11 NAG Library routines embedded within it. These work right from the LinearAlgebra package in the Maple Library, without the Connector or any extra NAG download or install.

> restart:

> with(LinearAlgebra):

> a := Vector[row](22,[1.0,1.0,-1.0,2.0,2.0,
>                      3.0,-2.0,1.0,-2.0,1.0,1.0],
>                  datatype=float[8]):

> irow := Vector[row](22,[1,1,2,2,2,3,3,4,4,4,4],
>                  datatype=integer[kernelopts('wordsize')/8]):

> icol := Vector[row](22,[2,3,1,3,4,1,4,1,2,3,4],
>                  datatype=integer[kernelopts('wordsize')/8]):

> A:=Matrix(4,4,storage=sparse,datatype=float[8]):
> for i from 1 to 11 do
>    A[irow[i],icol[i]]:=a[i];
> end do:

> A;
                             [ 0.   1.  1.   0.]
                             [                 ]
                             [-1.   0.  2.   2.]
                             [                 ]
                             [ 3.   0.  0.  -2.]
                             [                 ]
                             [ 1.  -2.  1.   1.]

> V:=Vector(4,(i)->i,datatype=float[8]);
                                       [1.]
                                       [  ]
                                       [2.]
                                  V := [  ]
                                       [3.]
                                       [  ]
                                       [4.]

> infolevel[LinearAlgebra]:=6:

> X:=LinearSolve(A,V);

LinearSolve: using method SparseIterative
LinearSolve: using method   SparseIterative
LinearSolve: calling external function
LinearSolve: using CGS method
LinearSolve: preconditioning with incomplete LU factorization
LinearSolve: level of fill =  0
LinearSolve: using complete pivoting strategy
LinearSolve: dimension of workspaces for preconditioner =  30
LinearSolve: using infinity norm in stopping criteria
LinearSolve: setting maximum iterations to  200
LinearSolve: setting tolerance to  0.10e-7
LinearSolve: NAG hw_f11zaf
LinearSolve: NAG hw_f11daf
LinearSolve: NAG hw_f11dcf
LinearSolve: number of iterations 1
LinearSolve: residual computed last as HFloat(4.440892098500626e-16)
                             [                   -16]
                             [4.44089209850063 10   ]
                             [                      ]
                             [     -1.50000000000000]
                        X := [                      ]
                             [      2.50000000000000]
                             [                      ]
                             [     -1.50000000000000]

> A.X-V;

unknown: hw_SpMatVecMulRR
                          [                     0.]
                          [                       ]
                          [                     0.]
                          [                       ]
                          [                    -16]
                          [-4.44089209850063 10   ]
                          [                       ]
                          [                     0.]

As you can see, the above uses f11daf, followed by f11dcf. Those are Fortran Library versions of the C Library functions f11dac and f11dcc.

There isn't an easy way to preserve the "incomplete LU factorization" results from f11daf, and to re-use such in multiple successive calls to f11dcf. Instead, both f11daf and f11dcf would get called together, each time LinearSolve got called. So if one has multiple RHS Vectors then it's better to solve them all at once, so as to factorize the Matrix only once. (An alternative would involve poking into the LinearAlgebra routine which does the individual external-calls to the compiled wrappers to f11daf and  f11dcf, and replicating the set-up of workspaces, external calls, etc, relevent to this real nonsymmetric sparse case.)

The SparseIterative method for nonsymmetric, numeric Matrices can also be forced in the call to LinearSolve, and some options specified. Eg,

   method=SparseIterative,methodoptions=[....]

Note that I did not have to use a triple of Vectors, `irow`, and `icol` and `a` above. I could have formed sparse nonsymmetric Matrix `A` in any fashion I wanted. Yes, it is true that the nonzero entries and their indices of a datatype=float[8] Matrix with storage=sparse are internally stored in three contiguous portions of memory: 2 arrays of hardware integers and one of hardware doubles. But there's no easy way to access those at the Maple Library command level without making an external call to a function which picks out those as three Vectors (using the "external API").

I better repeat the important bit: all the above works in Maple 14, 13, 12, etc, right from the LinearAlgebra package in the Maple Library, without the Connector or any extra NAG download or install. It should work in plain, installed Maple.

Now on to your more specific question about the Connector (if you still need to know, in light of the above).

You need a copy of the NAG C Library in order to run the commands in the Maple-NAG Connector product. (See point 1 of this help-page section "Before You Begin" for a mention of this fact.) See here, at NAG's own website, for some detail on obtaining the Mark 8 NAG C Library. (Their latest, the Mark 9, might not work.)

The underlying Chapter F11 sparse linear algebra functions of the NAG C Library are proprietary to NAG Ltd, UK, and as such won't run from the Maple-NAG Connector without a valid license to accompany that NAG C Library. This means that one has to purchase a NAG C Library license (from NAG), over and above the usual Maple license, in order to run such license-locked commands from the Connector.

The Connector is a bridge between these two distinct commercial products: Maple, and the NAG C Library. You need both products, and valid licenses for both products, in order to use the Connector in full.

Not all NAG C Library commands invoke license-locked NAG C Library functions. But the f11 ones are locked, if I recall correctly.

acer

restart:
st:=time():
evalf(Int(exp(-t)/(mul(-3+2*exp(-.1*(1-.1)^i*t), i = 0 .. 4)), t = 0 .. infinity));
time()-st;
                         -0.5821551499
                             25.803

restart:
st:=time():
evalf(Int(unapply(exp(-t)/(mul(-3+2*exp(-.1*(1-.1)^i*t), i = 0 .. 4)),t), 0 .. infinity));
time()-st;
                         -0.5821551499
                             0.031

restart:
st:=time():
evalf(Int(exp(-t)/(mul(-3+2*exp(-.1*(1-.1)^i*t), i = 0 .. 4)), t=0 .. infinity,
          method=_d01amc));
time()-st;
                         -0.5821551499
                             0.032

What I suspect is going on is that a lot of computational effort is (by default) being put into determining whether the integrand is singular in the given range. By forcing a method, or concealing the expression form of the integrand inside a procedure, some or all of this checking might be bypassed. (And, naturally, that would only be safe when one knows something of the qualitative behavior of the integrand.) That's my conjecture, anyway, though one could trace through `evalf/int/control` or something to see.

acer

Quite often French curves are sold alongside "ship's curves" for drafting. My understanding is that all this sort of thing predates the kind of math that we'd nowadays associate with such curves or their construction.

I found this ["A History of Curves and Surfaces in SAGD" by Gerald Farin] link interesting. It suggests that ship builders used to keep the large curved ribs used in building ships hulls, as templates. This goes with the notion that the curves would be built by hand, and that it predates the mathematicalization of such curves. It's plausible then, that smaller French curve construction might also have originally been by-hand. That linked paper does make a hint that Pascal and Monge might have somehow been involved in the methodology, but doesn't give detail on that. The link goes on to talk about Bezier and others who subsequently established the math behind such processes.

acer

Is this (post, or parent thread) close enough that you can hammer it to fit?

Or do you just need the -c option of the `maple` script? With that option (or multiple instances of it!) you can initialize the session, etc. Eg.  'maple -c "assign(...)"

% maple -s -c "assign(x,4)"

    |\^/|     Maple 14 (SUN SPARC SOLARIS)
._|\|   |/|_. Copyright (c) Maplesoft, a division of Waterloo Maple Inc. 2010
 \  MAPLE  /  All rights reserved. Maple is a trademark of
 <____ ____>  Waterloo Maple Inc.
      |       Type ? for help.
> x;
                                       4

acer

You'd want to set the system to 'FPS', so that simplification of units results in units of feet for the dimension of length.

Apart from the three ways shown below, you could alternatively use the right-click context-sensitive menu action Units -> Simplify on the output.

> restart:

> Units:-UseSystem('FPS');

> Z := 5*Unit('ft'):
> simplify(Z^2);

                                      [  2]
                                   25 [ft ]

> restart:

> Units:-UseSystem('FPS');
> with(Units:-Standard):

> Z := 5*Unit('ft'):
> Z^2;

                                      [  2]
                                   25 [ft ]

> restart:

> Units:-UseSystem('FPS');

> Z := 5*Unit('ft'):
> Z^2:
> combine(%, 'units');

                                      [  2]
                                   25 [ft ]

acer

There is a predefined system of units whose base units for mass and length are gram and centimeter (see here). There are other ways to change the default units for any given dimension, but let us know if this is not adequate for you.

Maple will keep Pi as an exact quantity by default. One can use the `evalf` command to approximate it to floating-point. By default, Maple will use the `Digits` environment variable to control the working precision (see here). One can also set the display precision for Standard GUI output (see here). It's usually better to let Maple use at least its default setting of Digits=10 for computation (and to separately control only the final display) than it is to downgrade the computation precision to something as low as Digits=5 (which might allow too much roundoff error for you on more complicated expressions). Below I use `evalf[5]` on just the final result, as a programmatic way to adjust the final displayed float value.

> restart:

> with(Units:-Standard):
> Units:-UseSystem(CGS);

> wirediameter:=.40*Unit(inch):
> wirelength:=1000*Unit(ft):
> wirevolume:=(wirediameter/2)^2 * Pi * wirelength: 
> wireweight:=61*Unit(lb):
> wiredensity:=evalf(wireweight/wirevolume):

> evalf[5](wiredensity);

                         [   g     ]
                  1.1197 [ ------- ]
                         [     3   ]
                         [   cm    ]

acer

Is this an attempt to phish for HD SNs associated with valid Maple licenses? (Isn't/wasn't HD SN an alternative to NIC SN for authentication?) Sorry if that sounds callous, but we live in troubled times.

acer

@turloughmack I apologize if I misinterpreted. The option price nomenclature part is technical jargon, and seems to obscure the fact that your difficulties seem to be with the coding aspects (which really are not specific to just that discipline). The jargon can obscure the question.

It might be better for legibility if you could use a notation that matched Maple's 1D notation, when posting the code as plaintext. For example, if your names are indexed then an entry for f might be f[i+1,j] and not f_i+1,j (which is what one might physically type, as 2D input). This is key, since even this interpretation might not be what you want. It seems that you might want the (i+1)th instance of a Vector f. In that case you could have a table of N Vectors f[i], with each member Vector having entries f[i][j], j=1..m. Or you might prefer to create an N by m Matrix f where each row represents a Vector and the indexing would be f[i,j].

It was pointed out in response to your earlier Question that square brackets are for list creation, and that you'd probably need round brackets as expression delimiters. But square brackets are still used above in the assignments of a[j], b[j], and c[j]. Is there a reason for that?

You've used `m` mostly, but in your setup of f[N] it appears that you really mean `M` (which is 10, as is N). Is that right? Is m supposed to be M, or vice versa?

Is this getting there?

restart:

a := j -> 1/2*(r-q)*j*Deltat - 1/2*sigma^2*j^2*Deltat:
b := j -> 1 + sigma^2*j^2*Deltat + r*Deltat:
c := j -> -1/2*(r-q)*j*Deltat - 1/2*sigma^2*j^2*Deltat:

r:= 0.05: Deltat:= T/N: DeltaS:=S/M: T:=0.4: q:=0: K:=1.1: S:=2: M:=10: N:=10:

thematrix := Matrix(M,M,scan=band[1,1],
            [[seq(a(j),j=1..M-1)],
             [seq(b(j),j=1..M)],
             [seq(c(j),j=1..M-1)]]):

f[N]:=Vector(M,(j)->max(K-j,DeltaS,0)):

thismatrix:=eval(thematrix,sigma=0.9):

for i from N to 2 by -1 do
 f[i-1] := LinearAlgebra:-LinearSolve(thismatrix,f[i]);
end do:

f[1];

invthismatrix:=thismatrix^(-1):
invthismatrix^9 . f[N];

It might be slightly more numerically stable to do the repeated LinearSolve, over MatrixInverse. But at this size problem any efficiency concerns and tweaks (re-using the LU decomposition, done just once) would make the code less clear for a negligible benefit I suspect.

Maybe the brute force way would do: find the x,y (err, Q1,Q2) values at the intersections. Then just draw eight curves instead of four. And have some of the eight get the dashed line style. See ?plot,option on chenging the line style.

Instead of creating all curves in a single plot structure right away, you could assign each to a name. Ie, P1:=plot3(....,Q1=-1..X, Q2=-1...1) where X is the Q1-coordinate of the intersection point. Analogously for the other curves, but some with the line style specified as an option. Then use plots:-display to show them all superimposed.

acer

What precisely do you mean by "prints itself"? Do you mean that calling it will produce as output the same result as would evaluating (or printing) it?

I have set interface(prettyprint=1) for these examples below.

> f:=proc() print(eval(procname)); end proc;
                 f := proc() print(eval(procname)) end proc;

> f();
proc() print(eval(procname)) end proc;

Note that the above does not work when the procedure is anonymous. But for that case, one can use the new (as of Maple 14, see here) `thisproc`,

> f:=proc() print(eval(procname)); end proc:

> %(); # NULL output, ie. it didn't succeed

> proc() print(eval(thisproc)); end proc;
proc() print(eval(thisproc)) end proc;

> %();
proc() print(eval(thisproc)) end proc;

It occurs to me that perhaps you instead mean that you want the result of calling `f` to simply be the name of f.

> f:=proc(x)
>    debugopts('callstack')[2];
> end proc:

> f();
                               f

> g:=proc() f(); end proc:
> g();
                               f

I found that callstack useful when coding a redefined version of (the protected) `userinfo` which would display results to a Text Component. This worked even when the code was run in a Maplet or other "hidden" facility, and it worked without having (access) to change or edit the original routine sources. The task was harder still -- to find out how the current parent procedure had been called. I'd meant to blog it...

Another way to get this simpler effect of printing only the current procedure's own name might be,

> f:=proc() op(1,''procname''); end proc:

> f();
                               f

Do either of those two interpretations of "prints itself" come close to your intended meaning?

acer

Hey Axel, I see you're still musing over that usenet post. One might easily get Maple to convert the following roots of that quintic to radicals, by just calling `solve` with its Explicit option.

> seq(cos(i*Pi/11),i in [1,3,5,7,9]);

           /1    \     /3    \     /5    \      /4    \      /2    \
        cos|-- Pi|, cos|-- Pi|, cos|-- Pi|, -cos|-- Pi|, -cos|-- Pi|
           \11   /     \11   /     \11   /      \11   /      \11   /

But these roots of that sextic look like they are going to be a little tougher... ;)

seq(cos(i*Pi/13),i in [1,3,5,7,9,11]);

    /1    \     /3    \     /5    \      /6    \      /4    \  
 cos|-- Pi|, cos|-- Pi|, cos|-- Pi|, -cos|-- Pi|, -cos|-- Pi|, 
    \13   /     \13   /     \13   /      \13   /      \13   /  

       /2    \
   -cos|-- Pi|
       \13   /

acer

First 279 280 281 282 283 284 285 Last Page 281 of 336