acer

32385 Reputation

29 Badges

19 years, 336 days
Ontario, Canada

Social Networks and Content at Maplesoft.com

MaplePrimes Activity


These are answers submitted by acer

You can have a Maple procedure open an interactive file-manager dialogue (popup) to allow you two browse directories and/or filenames.

And the resulting fully qualified filename (location) can be used for the plot export.

Is this along the lines you are thinking?


restart;

plotsetup(); # original settings

preplot = "", postplot = "", plotdevice = inline, plotoutput = terminal, plotoptions = ""

plotexport:=module()
  local ModuleApply, maplet;

  maplet:=Maplets:-Elements:-Maplet(Maplets:-Elements:-FileDialog['FD1'](
    ':-onapprove' = Maplets:-Elements:-Shutdown(['FD1']),
    ':-oncancel' = Maplets:-Elements:-Shutdown()
  )):

  ModuleApply:=proc( P::specfunc(:-anything,{:-PLOT,:-PLOT3D,:-ISOSURFACE}),
                     device::string:="jpeg",
                     {filename::string:=""} )
                 local fn, orig, worig;
                 orig:=select(type,[plotsetup()],
                                    identical(':-plotoutput',':-plotoptions',
                                              ':-plotdevice')=anything);
                 fn:=Maplets:-Display(maplet);
                 if fn::list and nops(fn)>0 and fn[1]::string then
                   worig:=interface(':-warnlevel'=0);
                   fn:=fn[1];
                   try
                     plotsetup(device,':-plotoutput'=fn,_rest);
                     print(P);
                     fclose(fn);
                   catch:
                   finally
                     plotsetup(eval(':-plotdevice',orig),
                               ':-plotoutput'=eval(':-plotoutput',orig),
                               ':-plotoptions'=eval(':-plotoptions',orig));
                     interface(':-warnlevel'=worig);
                   end try;
                   plotsetup(eval(':-plotdevice',orig),
                               ':-plotoutput'=eval(':-plotoutput',orig),
                               ':-plotoptions'=eval(':-plotoptions',orig));
                   interface(':-warnlevel'=worig);
                 else
                   return NULL;
                 end if;
                 NULL;
               end proc:
end module:

plotexport(plot(sin),"bmp",plotoptions="height=100,width=400");

plotexport(plot(sin),plotoptions="height=100,width=400"); # jpg

plotsetup(); # original settings restored

preplot = "", postplot = "", plotdevice = inline, plotoutput = terminal, plotoptions = ""

 


Download plotexport.mw

How fancy do you want it? Do you want additional panels in the popup, to allow you to enter the resolution? And to pick the image format from a menu?

I don't think that the usual methods will allow us to augment the context-menu that appears when right-clicking on an inlined plot. That could be a nice finishing touch.

acer

Are you typing in end proc (or just end) to terminate the proc ?

Are you hitting the Enter key too early, before you terminate the proc with an end or end proc?  If you want to type in a procedure as multi-line text then use Ctl-Enter (or Cmd-Enter on OSX) instead of Enter in order to move the input prompt to a new line below.

How about using the Green up-arrow here to attach an example of your failed attempt in a worksheet?

acer

Your integrand is a polynomial in omega and in that sense its coefficients are functions of only x.

If you integrate this polynomial (in omega) term by term with respect to x then the result will be a new polynomial in omega where each coefficient is the integral (wrt x) of the previous polynomial (integrand).

In other words, you start with A*omega^2+B*omega+C where A, B, and C are each expressions in terms of just x. You want to approximate Int(  A*omega^2+B*omega+C, x=0..L ) . So If you form that instead as  omega^2*Int(A,x=0..L) + omega*Int(B,x=0..L) + Int(C,x=0..L) then the integrals can be computed purely numerically.

It remains to program that. There are several ways to get it. I'll do it first by constructing the target polymial (with Int coefficient) explicitly, to try and make things clear.

restart

Digits := 15:
 

``

ee := H22*x*(cos(varepsilon*((1/2)*L-x)/R)+kappa*cosh(varepsilon*((1/2)*L-x)/R)):

type(collect(ee, omega), polynom(anything, omega))

true

plist := PolynomialTools:-CoefficientList(collect(ee, omega), omega); -1; newerint := add(w^(i-1)*(Int(simplify(plist[i]), x = 0 .. L)), i = 1 .. nops(plist)); -1; CodeTools:-Usage(evalf(newerint))

0.193138121006038e-11-0.295229265242607e-29*w^2

NULL

Download approxint.mw

The final line of that took less than 1 second to compute on my Intel i5 running 64bit Maple 2016.0 for Linux.

It turns out that applying simplify to the integral (after collecting wrt omega) will also produce the target form that computes quickly. But I think it still helps to understand that it can be formed explicitly as above. So, after the assigment of the integrand to name ee, those later steps could alternatively just be done as,

newint := CodeTools:-Usage( simplify(map(Int, collect(ee, omega), x = 0 .. L)) ):

memory used=15.31MiB, alloc change=0 bytes, cpu time=116.00ms, real time=119.00ms, gc time=16.00ms

type(%, polynom(anything, omega));

                              true

CodeTools:-Usage( evalf(newint) );

memory used=367.94KiB, alloc change=0 bytes, cpu time=0ns, real time=3.00ms, gc time=0ns

                              -30      2                      -12
          -2.95229265242607 10    omega  + 1.93138121006038 10   

acer

This is a frequently asked question.

restart:                        

ode := diff(f(x), x) = 2*x+6:   
init := f(0) = 12:              

sol:=dsolve({init, ode});       
                                                               2
                                                sol := f(x) = x  + 6 x + 12

g := unapply(rhs(sol)*exp(x),x);
                                                          2
                                              g := x -> (x  + 6 x + 12) exp(x)

g(2);                           
                                                         28 exp(2)

# Or...
f:=unapply(rhs(sol),x);
                                                             2
                                                  f := x -> x  + 6 x + 12

g:=x->f(x)*exp(x);
                                                   g := x -> f(x) exp(x)

f(2);
                                                             28

g(2);
                                                         28 exp(2)

acer

I have mostly kept your basic structure, as you are trying stuff out. That's fine, of course.

I did pull the call to `rand` outside of the procedure body. But you could also declare `r` as another local of `dice`, and have the assignment to `r` be inside the procedure. Both these ways will work.

Note that the call rand(1..2) returns a procedure, which can itself be called to generate random values. But if you assign the proc returned by rand(1..2) to some name and then you also assign a random value (1 or 2, produced by it) to that very same name then you are clobbering the name and you won't be able to generate more than one random value. So I use two names below, `r` and `roll`.

You forgot the end proc in your code.

restart;

randomize():

r := rand(1..2):

r(), r(), r(), r(), r();

                                2, 1, 2, 1, 1

dice:=proc()
local count, i, roll;
  count:=0:
  for i from 1 to 10000 do
    roll:=r();
    if (roll=1) then count:=count+1 end if;
  end do;
  return count;  
end proc:

dice();

                                    4986

dice();

                                    5047

You could compare these:

plot(x^2,x=0..1);

plot(x^2,x=0..1,axis=[thickness=3,tickmarks=[thickness=3]]);

plot(x^2,x=0..1,thickness=3,axis=[thickness=3,tickmarks=[thickness=3]]);

acer

You can look at Kitonum's great post about labeled contours (which I suspect could be adjusted to use a legend with color-coded lines/polygons with correspondingly nice legend labels).

And I'd be surprised if this method of displaying a surface beside a colorbar couldn't be adjusted to instead marry a 2D contour plot with a colorbar.

But I never get tired of this subject, so for fun here's yet another way to get some color-coding in a legend. This needs the Standard Java GUI. I ran this below in Maple 18.02.

restart:

with(ColorTools):

expr := 0.3109032081e-3*exp(-0.3042543475e-4*(x-400)^2
                     -4.512172305*10^(-7)*(x-400)*(a-3.576693)
                     -0.3179826080e-1*(a-3.576693)^2):

c1:=[Color("#500090")[]]:
c2:=[Color("#ffffdd")[]]:

clist:=[seq(Color(c1+(i-1)*(c2-c1)/5), i=1..6)]:
contlist:=[seq(0.0 .. 0.00025, 0.00005)]:

plots:-display(
  plots:-contourplot(expr, x=0..800, a=0..25, filledregions,
                     coloring=[clist[1], clist[-1]], contours=contlist),
  seq(plot([[0,0]], color=white, axes=none,
           legend=typeset(nprintf("#mrow(mn(\".    .\",mathbackground=%a),mi(\"gt;\"))",
                                  RGB24ToHex(RGBToRGB24([clist[i][]])))
                          ,contlist[i])),
      i=nops(clist) .. 1, -1),
  legendstyle=[location=right],
  size=[550,400], axes=box);

Download contourlegend1.mw

acer

For the Standard Interface, with typesetting level set to extended.

This doesn't change the structure in memory. It just prints the thing differently. It could be streamlined or customize/extended for other uses.

 

restart;

interface(typesetting=extended):

Expr:=a*diff(x(t),t)+b*x(t)+r*diff(x(t),t,t)+a*diff(y(t),t)+b*diff(y(t),t,t)+c*y(t):

`print/Asc`:=proc(ee)
  local S;
  uses PDEtools,Typesetting;
  S:=sort([`if`(ee::`+`,op(ee),ee)],(a,b)->(difforder(a)<difforder(b)));
  Typesetting:-mrow(Typeset(EV(S[1])),
                    seq([mo("&plus;"),Typeset(EV(S[i]))][],i=2..nops(S)));
end proc:

`print/Desc`:=proc(ee)
  local S;
  uses PDEtools,Typesetting;
  S:=sort([`if`(ee::`+`,op(ee),ee)],(a,b)->(difforder(a)>difforder(b)));
  Typesetting:-mrow(Typeset(EV(S[1])),
                    seq([mo("&plus;"),Typeset(EV(S[i]))][],i=2..nops(S)));
end proc:

Asc(Expr);

Asc(a*(diff(x(t), t))+b*x(t)+r*(diff(diff(x(t), t), t))+a*(diff(y(t), t))+b*(diff(diff(y(t), t), t))+c*y(t))

Desc(Expr);

Desc(a*(diff(x(t), t))+b*x(t)+r*(diff(diff(x(t), t), t))+a*(diff(y(t), t))+b*(diff(diff(y(t), t), t))+c*y(t))

Expr;

a*(diff(x(t), t))+b*x(t)+r*(diff(diff(x(t), t), t))+a*(diff(y(t), t))+b*(diff(diff(y(t), t), t))+c*y(t)

 

 

Download typsetorder.mw

With a variation on the sort predicate (used above) it might also force the relative order of terms with x(t) versus y(t). And so on.

A quite different approach might be to replace the diff calls with individual objects (which each print the diff represented) and then sort according to those (via indirection, to the desired diff order as the sorting key).

acer

If you are really striving to get something like long multiplication (as learned in grade school, say), then you could try something like the following.

Note that it does not discriminate between trailing zeros and other trailing digits. See my querying comments above -- I was trying to figure out what you wanted beyond the meagre example you supplied. I may have surmised wrongly.

restart;

h:=proc(f1::float, f2::float)
     Float(op(1,f1)*op(1,f2),op(2,f1)+op(2,f2));
   end proc:

a:=.123456789:

h(a, a);

0.15241578750190521e-1

h(0.1, evalf(1/3));

0.3333333333e-1

h(1., a);

.123456789

h(1.00, a);

.12345678900

h(0.1, a);

0.123456789e-1

h(0.100, a);

0.12345678900e-1

 

Download star1.mw

Now, if those result are acceptable and if you really want the interactive `*` command to behave like that then you could try and enhance something like the following very rough idea. Note that I have not implemented distribution across sums, and also note that overloading arithmetic operators can lead to weird usage problems (because the symbols often server multiple purposes).

p:=module() option package; export `*`;
     `*`:=proc(aa::seq(Non(:-`+`)),$)
       local a,r,sf,sn,so,sr;
       sn,so:=selectremove(type,[seq(`if`(type(a,:-`*`),
                                          op(a),a),
                                     a=args)],numeric);
       if sn=[] then return :-`*`(so[]); end if;
       sf,sr:=selectremove(type,sn,float);
       if sf=[] then return :-`*`(so[],sr[]); end if;
       sf:=[sf[],evalf(sr)[]];
       r:=Float(mul(op(1,f),f=sf),add(op(2,f),f=sf));
       if so=[] then r;
       else :-`*`(so[], r);
       end if;
     end proc:
   end module:

a:=.123456789:

with(p):

a * a;

0.15241578750190521e-1

0.1 * 1/3;

0.3333333333e-1

0.100 * a;

0.12345678900e-1

a * t;

.123456789*t

`*`();

1

a * t * a * 1/s;

0.15241578750190521e-1*t/s

1/3 * t * 1/4 * 1/s;

(1/12)*t/s

a * (t + a);

Error, invalid input: too many and/or wrong type of arguments passed to `*`; first unused argument is t+.123456789

 

Download star2.mw

This is probably a good time to take a step back. What are your underlying, motivating examples that make you think that you want this behavior? Very, very often here on mapleprimes people ask about how to implement a scheme they've cooked up to solve some problem, when there exists some better way. So if, for example, you are "just" trying to deal with roundoff error for non-atomic, composed elementary computations (and noticed that --unlike Mathematica -- Maple does not accomodate specifying an inbound accuracy for float inputs) then you may be better off with a scheme involving intervals/evalr/shake/etc.

acer

I too see the problem. (The "strange characters" seems to be the colon-equals symbols that are rendered below the start of the numerator.

A shorter code to reproduce, for me,

r:=175!/(11111);

acer

If you mean the Fourier package by Karel Srot that is described here on the Application Center then you can try this URL which contains some older zip file links to it.

acer

@Hapseeker What you gave to us a plaintext is, it seems, some 2D Math input in which you are using the statement p_com(z,t):=... to create an operator. Several experts here consider that syntax as dubious at best, because it is ambiguous.

I suggest that instead such an operator is constructed either with the more usual, unambiguous arrow syntax, or something like this if you wish to make use of the assumptions before constructing the body of the operator (without the Re call). The key thing I use in getting the call to Re resolved away in the operator body is the unapply command.

restart;

p_com := unapply(Re(exp(I*omega*t-I*k*(lambda[r]+I*lambda[i])*z)), [z,t])
           assuming omega::real, t::real, k::real, lambda[r]::real, lambda[i]::real, z::real;

One way is to use the freeze command. Eg,

eq := (-Omega^2*a*A[2]-Omega^2*m*B[1]+Omega*A[1]*c[1]+B[1]*k[1])*cos(Omega*t)
      +(Omega^2*a*B[2]-Omega^2*m*A[1]-Omega*B[1]*c[1]+A[1]*k[1])*sin(Omega*t)
      = 0:

fexpr:=subs([sin(Omega*t)=freeze(sin(Omega*t)),
             cos(Omega*t)=freeze(cos(Omega*t))],(lhs-rhs)(eq)):

coeff(fexpr, freeze(sin(Omega*t)));

           2               2                                     
      Omega  a B[2] - Omega  m A[1] - Omega B[1] c[1] + A[1] k[1]

coeff(fexpr, freeze(cos(Omega*t)));

            2               2                                     
      -Omega  a A[2] - Omega  m B[1] + Omega A[1] c[1] + B[1] k[1]

acer

More succinctly,

restart:

assume(b()(x),real);

getassumptions(a(x));

                        {(b()(x))::real}

[edited, all below] And, shorter still,

restart;

assume(b(t),real);

getassumptions(a(t));

                                              {b(t~)::real}


What's happening is that the assumption that b(t)::real involves t, and this semantic baggage of t affects tests of properties of a(t). And getassumptions(a(t)) is simply reporting the semantic baggage of t to the extent that it knows any property related to t.

about(t);

Originally t, renamed t~:
  Involved in the following expressions with properties
    b(t) assumed real
  also used in the following assumed objects
  [b(t)] assumed real

coulditbe( a(t), real );

                                                   FAIL

Whereas in a fresh session,

restart;

coulditbe( a(t), real );

                                                   true

Perhaps another example might help illustrate why this behavior can be useful.

restart;

assume(sqrt(t)>3);   

getassumptions(a(t));

        1/2            1/2
     {t~   ::real, (-t~    + 3)::RealRange(-infinity, Open(0)),

                      1/2
                   (t~    - 3)::RealRange(Open(0), infinity)}

is(t<2);             

                                                  false

acer

@JacquesC I am surprised that you are surprised.

I don't see why you focus on ctx as a keyword parameter of foo. Consider the case where ctx is a required parameter. The requirements on how to use the name ctx when calling bar are the same as for your examples.

The essence of your problem is not in the particular value of parameter ctx when inside foo, but rather it is in the usual rules for how one may not use (the name of) a formal parameter as a name within a procedure. Eveluation of the parameters happens up front, not at each instance they are used within the running procedure.

Are you surprised by how the first example below works? If not then why should keyword parameter values get into procs differently than do required parameters?

restart;

foo := proc( ctx )
         'ctx' = [a,b,c];
       end proc:

foo( 7.3 );
                        7.3 = [a, b, c]

restart;

foo := proc( ctx )
         :-ctx = [a,b,c];
       end proc:

foo( 7.3 );
                        ctx = [a, b, c]

The only thing mildly surprising to me here is that the need to denote a keyword as only a name was not made a strict requirement by design. I have heard %ctx=[a,b,c] or "ctx"=[a,b,c] as suggestions in the past. It would have to be strictly required if it were not going to trip up users, because otherwise many of them will use a shorter syntax like ctx=[a,b,c] by habit simply because it works most of the time. But it's too far late now to enforce such a requirement.

I see the form ':-ctx'=value being used a great deal. I don't see why it would be surprising that the global name is necessary if one wants to use a name (as a name) that happens to also be that of a formal parameter. And mint will tell you that you need the quotes, if you tried it as :-ctx=value instead.

Also the kernel should not be allowed to use the name ctx when passing ctx=value to bar, as if ctx were just a name, if ctx also happens to be the name of a formal parameter. If that were the behaviour then we wouldn't be able to pass sensibly the argument value_of_ctx=blah as well as the argument name_ctx=blech to bar. In other words, the following should be allowed to all work as it does now:

restart;

f := proc( { ctx :: list := [] } )
       g( ctx=[q,r,s], ':-ctx'=[a,b,c] );
     end proc:

g := proc( ListEq, { ctx :: list := [] } )
       [_passed], [_options[1.._noptions]];
     end proc:

f( );

            [[] = [q, r, s], ctx = [a, b, c]], [ctx = [a, b, c]]

f( ctx=[1,2,3] );

         [[1, 2, 3] = [q, r, s], ctx = [a, b, c]], [ctx = [a, b, c]]
First 212 213 214 215 216 217 218 Last Page 214 of 336