Joe Riel

9660 Reputation

23 Badges

20 years, 4 days

MaplePrimes Activity


These are answers submitted by Joe Riel

xbar indicates the complex-conjugate of x.  Add the option conjugate=false in the call to MatrixNorm to prevent taking conjugates.

e is not assigned the Euler number in Maple.  Long ago, E was used for that purpose.  Now nothing is preassigned.  You could do e := exp(1), but the better solution is to convert your e^x to exp(x), because e^x, with e = exp(1), is not the same as exp(x).

The usual solution is with map:

L := [a=2,b=3,c=4]:
map(rhs, L);
                            [2,3,4]

To swap the lhs and rhs of the equations, do

map(rhs=lhs, L);
                   [2=a, 3=b, 4=c]

You will probably want to save your module to a custom Maple archive so that you can use it from any Maple session, provided it can access that archive.  Saving the module is easy enough, assuming you have a writable directory with path /home/si37/maple:

LibraryTools:-Save('foo', "/home/si37/maple/myarchive.mla"):

The next step to modify the global variable libname so that Maple can find this archive.  I do that by creating a Maple initialization file and inserting the line

libname := "/home/si37/maple", libname:

See the Maple help page worksheet,reference,initialization for details on the location of the initialization file. Maple reads this file every time it starts and executes the Maple commands contained within.  The above assignment to libname prepends your custom archive directory to the existing libname sequence.

 

There are two related problems, both somewhat subtle, with this routine.  First, the Maple procedure convert/symbol returns a global symbol.  As such, it will not match the local symbols (variables) in the procedure.  A better way to handle this translation is via a table, however, for now let's just use what you have.  The simplest change is to redeclare the symbols M, M2, ..., M10, and X to be global.  That, alas, does not suffice.  The reason is that inside a procedure Maple only evaluates expressions one level.  When you do map(convert, s, symbol) the result is a list of symbols, not a list of their values.  It is those values which foldl gets and chokes.  A work-around for that is to fully evaluate the list, that is add the statement s := eval(s) [before the call to op(s)).  With those changes the procedure operates.

As mentioned, a better way to do this is with a table.  Create the table

MIX := table(["X" = [[1,12], ...], "M" = [...], ..., "M10" = [...]):

then instead of converting s to symbols, look up the strings in the table

s := [seq([MIX[char], char in s)];

Actually, I'd probably do that inside the loop that parses the individual characters.

Are you just trying to draw a nice graph, or are you attempting to fit a particular parameterized curve to the data?  If so, what equation do you expect?

The equation is not symmetric, look at the denominators.

 map(denom,lhs(eq)); 
                                              2
                                          A(r)  + A(r) B(r) + B(r)

You might consider the following:

angles1_dif := map(L -> L[..-2]-L[2..], angles1_s);

Note that angles1_dif here is a list, not a sequence.  It is usually better to use a list when you will be later selecting from it, otherwise you get unexpected results if there is only 1 item.

Rather than sorting and picking the first element, use min

for i to nops(angles1_s) do
   member(min(angles1_dif[i][]), angles1_dif[i], 'k');
   print(angles1_s[i][k], angles_s[i][k+1]);
end do:

A limitation of my previous response is that it depended on dsolve being able to solve the differential equations symbolically.  Here is a modification that uses dsolve/numeric.  Note that I used the optional parameter 'initialvalues' in the call NonlinearFit, that was necessary to avoid a range that dsolve could not integrate.  This is slower, it takes about 45 seconds.

T := Vector([0., 10.0, 20.0, 31.0, 41.0, 52.0, 63.0, 101.0, 118.0, 146.0, 175.0]):

Z := Vector([NULL
             , 0.26134778186274507e-1
             , 0.5998907077205882e-1
             , 0.9122613357843135e-1
             , .15470589797794115
             , .15113937469362743
             , .17105442156862743
             , .2182091648284313
             , .13516658731617642
             , .10597567371323527
             , 0.8211602236519606e-1
             , 0.7081520343137254e-1
            ]):

L := piecewise(t<=63
               , c*(F*(1-exp(-Delta*t))   + beta*exp(-Delta*t))
               , c*(F*(1-exp(-Delta*tau)) + beta*exp(-Delta*tau))*exp(-Delta*(t-tau))
              ):

GivenParams := {F=0.015,c=4.46,Delta=0.088,beta=0.007,tau=63}:

deqs := {NULL
         , -diff(y(t),t)+2*p1*f*L-p1*y(t)
         , -diff(x(t),t)+2*p2*(1-f)*L-p2*x(t)
         , x(0) = 0, y(0) = 0
        }:

dsol := dsolve(eval(deqs, GivenParams), {x,y}(t), 'numeric', 'parameters'=[p1,p2,f]):

z := (x(t)+y(t))/2/F/c:
znum := eval(z, GivenParams):

zcompute := proc(t,p1,p2,f)
    dsol('parameters' = [p1,p2,f]);
    eval(znum, dsol(t));
end proc:

FoundParams := Statistics:-NonlinearFit(zcompute, T, Z
                                        , output=parametervalues
                                        , initialvalues = <.01, .001, 0.1>
                                       );

dsol('parameters' = convert(FoundParams,'list'));
plt_fit := plots[odeplot](dsol, [t, znum], 0..175):
plt_data := plot(zip(`[]`,T,Z), style=point):

plots:-display([plt_data,plt_fit]);

 

Here is how I might approach that, using Statistics:-NonlinearFit.

T := Vector([0., 10.0, 20.0, 31.0, 41.0, 52.0, 63.0, 101.0, 118.0, 146.0, 175.0]):

Z := Vector([NULL
             , 0.26134778186274507e-1
             , 0.5998907077205882e-1
             , 0.9122613357843135e-1
             , .15470589797794115
             , .15113937469362743
             , .17105442156862743
             , .2182091648284313
             , .13516658731617642
             , .10597567371323527
             , 0.8211602236519606e-1
             , 0.7081520343137254e-1
            ]):

L := piecewise(t<=63
               , c*(F*(1-exp(-Delta*t))   + beta*exp(-Delta*t))
               , c*(F*(1-exp(-Delta*tau)) + beta*exp(-Delta*tau))*exp(-Delta*(t-tau))
              ):

GivenParams := {F=0.015,c=4.46,Delta=0.088,beta=0.007,tau=63}:

deqs := {NULL
         , -diff(y(t),t)+2*p1*f*L-p1*y(t)
         , -diff(x(t),t)+2*p2*(1-f)*L-p2*x(t)
         , x(0) = 0, y(0) = 0
        }:

dsol := dsolve(eval(deqs, GivenParams), {x,y}(t)):

z := x(t)+y(t)/2/F/c:

znum := subs(dsol, GivenParams, z);

FoundParams := Statistics:-NonlinearFit(znum,T,Z,t,output=parametervalues);

zfit := eval(znum,FoundParams);

plt_data := plot(zip(`[]`,T,Z), style=point):
plt_fit  := plot(zfit, t=0..180):

plots:-display([plt_data,plt_fit]);

This takes about 10 seconds of compute time (mostly in dsolve).

There might be a cute way around this, though I'm not wild about it. Use the seq parameter modifier and then use indexed values to access the parameters.  For example

f := proc(x :: seq(anything))
       x[1] + x[2]
end proc:

If you are entering the procedure in 2D mode, which is, I suppose, the whole point of the exercise, then you would type x[1] and x_1, and the result would appear nicely typeset.

There are issues with this.  First, it means you are entering code in 2D format, something that is better not done.  It isn't as robust as 1D input and is slower, since it has to be translated. Second, it only works in limited applications, where the seq modifier can be used.  For example, unless you can specify a type that distinguishes them (anything won't work), you cannot reliably use the seq modifier with consecutive formal parameters. Third, using index notation with a sequence can give unexpected results, for example, if there was but one argument and it was a list.  Then x[2] would correspond to the second element of the list (rather than the non-existent second argument).  When using the seq modifier, it is usually best to convert the sequence to a list, as recommended in the parameter_modifiers help page.

It's generally best if a procedure does not depend on a package having been 'withed'.  That is, rather than doing

with(group): with(StringTools): with(Maplets[Examples]):
IM := proc() ... end proc:

you should do

IM := proc()
uses group, StringTools, Maplets:-Examples;
...
end proc:

There appears to be a superfluous convert(s,'list') in the procedure (s was previously converted to a list).  Regardless, if I understand what you intend, it is better to do s := map(convert, s, symbol) rather than assigning elements of a list, which is not efficient and only works for relatively small lists (less than 100 elements).

Also, backquotes around foldl serve no useful purpose

Here's a modification that returns the sequence of sets.  Enclosing it in set braces then returns the unique solutions.

subsetsum := proc(X,Y,N) # X is a set, N is an integer
local x,Ysum;
    Ysum := add(x, x in Y);
    if Ysum = N then
        return Y;
    elif Ysum < N then
        seq(`if`(Ysum + x <=  N
                 , procname(X,Y union {x}, N)
                 , NULL
                )
            , x in X minus Y
           );
    end if;
end proc:

{subsetsum({1,2,4,7,10,11},{},25)};
                    {{4, 10, 11}, {1, 2, 4, 7, 11}}

Depending on the file format, you might be able to use readdata directly. Another possiblity is to use fscanf instead of the readline/parse combination.

It's a bug/limitation of plots[display].  I'll submit it as such.  Here's a simple demo of it:

p1 := plot(sin(x), x=0..Pi):
plots[display](p1, font=[TIMES,BOLD,12]);
plots[display](p1, labelfont=[TIMES,BOLD,12]);

A workaround is to use labelfont in the original plot commands.
First 91 92 93 94 95 96 97 Last Page 93 of 114