Carl Love

Carl Love

28095 Reputation

25 Badges

13 years, 100 days
Himself
Wayland, Massachusetts, United States
My name was formerly Carl Devore.

MaplePrimes Activity


These are answers submitted by Carl Love

The following will produce a very smooth curve that fits the data rather closely.

m:= min(y_data): M:= max(y_data):
Y:= [seq(m..M, (M-m)/100)]:
X:= CurveFitting:-ArrayInterpolation(y_data, x_data, Y, degree= 3, method= spline):
plot(zip(`[]`, Y, X));

Since you said that you don't quite understand the math behind it, here it is in more detail.

F:= (x,y)-> x*(x+y)*exp(y-x):

We first note that the function is differentiable for all x and y.

Compute all first partial derivatives.
dFdx:= simplify(D[1](F)(x,y));

dFdy:= simplify(D[2](F)(x,y));

Set first partial derivatives to 0 and solve simultaneously. In the language of analytic geometry, this corresponds to finding where the tangent plane is horizontal. In the language of vector calculus, we would say that these points are where the gradient is 0. These points are called critical points.

CritPts:= [solve({dFdx=0, dFdy=0}, {x,y})];

Now we need to classify the critical points as minima, maxima, or saddle points. Algebraically, the easiest way to do this is to use the second derivatives. Since we have a computer algebra system, that's the way that we'll use.

Compute the matrix of second partial derivatives, which is called the Hessian.

Hess:= Matrix(2, (i,j)-> simplify(D[i,j](F)(x,y)));

We evaluate the Hessian at each critical point and then compute the eigenvalues. If all the eigenvalues are positive, the point is a minimum. If all the eigenvalues are all negative, it's a maximum. If some eigenvalues are positive, some are negative, and none are zero, then it's a saddle point. If any eigenvalues are zero, the test is inconclusive.

for cp in CritPts do convert(evalf(LinearAlgebra:-Eigenvalues(eval(Hess, cp))), list) od;
                  [2.414213562, -0.414213562]
                  [0.3543123712, 0.0516934784]

So (0,0) is a saddle point and (1/2, -3/2) is a minimum.

 

(Man, I'm sick and tired of posting whole worksheets by cutting and pasting each paragraph separately! Please fix this so that I can upload whole worksheets! Sometimes it works for me, sometimes not.)

The command Maplets:-Elements:-TextField has an option tooltip= "...". That's what you want. See ?Maplets,Elements,TextField

I wrote you a module (actually a module-valued proc) to help with the process of building an animation:

Frames:= proc()
    module()
    local frame:= 0, Frames:= table();
    export
         Add:= proc(P::seq(specfunc(anything, {PLOT,PLOT3D,ANIMATE})))
              frame:= frame+1;  
              Frames[frame]:= `if`(nargs=1, P, plots:-display(P))
         end proc,
         Animate:= ()-> plots:-display(convert(Frames, list), insequence),
         New:= proc()  frame:= 0;  Frames:= table()  end proc
     ;
     end module
end proc:

At the beginning of your worksheet, or somewhere before the first plot that you want included in the animation, include the line

GamesAnim:= Frames():

(The GamesAnim can be any name that you like.) Every time that you generate a frame (any plot that you want in the animation), use the module export Add:

GamesAnim:-Add(P1,P2);

When you want the animation, use

GamesAnim:-Animate();

If you want to start a new animation using the same kernel memory, use

GamesAnim:-New();

Here is your worksheet with these features added:

posterior_graphs_(animated)_1D.mw

Attempting to use solve to isolate the derivative provides a clue. For some inexplicable reason, the pieces of the piecewise are re-expressed as one-element lists rather than as simple expressions. After converting them back to expressions, the DEplot works fine with arrows.


restart;

with(DEtools):

de:= Pi*(1+(3/5)*h(t))^2*(diff(h(t), t)) = piecewise(t<60, 2, t<150, 9, 6)- Pi*sqrt(2*h(t)):

solve(de, diff(h(t),t));

piecewise(t < 60, [-(25*(Pi*sqrt(2)*sqrt(h(t))-2))/(Pi*(9*h(t)^2+30*h(t)+25))], t < 150, [-(25*(Pi*sqrt(2)*sqrt(h(t))-9))/(Pi*(9*h(t)^2+30*h(t)+25))], 150 <= t, [-(25*(Pi*sqrt(2)*sqrt(h(t))-6))/(Pi*(9*h(t)^2+30*h(t)+25))])

evalindets(%, list, op);

piecewise(t < 60, -(25*(Pi*sqrt(2)*sqrt(h(t))-2))/(Pi*(9*h(t)^2+30*h(t)+25)), t < 150, -(25*(Pi*sqrt(2)*sqrt(h(t))-9))/(Pi*(9*h(t)^2+30*h(t)+25)), 150 <= t, -(25*(Pi*sqrt(2)*sqrt(h(t))-6))/(Pi*(9*h(t)^2+30*h(t)+25)))

de:= diff(h(t),t) = %:

DEplot(de, h(t), t= 0..300, [h(0)=10], h(t)= 0..11):

plots:-display(%, gridlines= false);

 


Download DEplot-bug-solved.mw

Use the define command:

define(L, orderless, multilinear);
L(2*y1(x)+3*y2(x), 5*z1(x)+7*z2(x));



Many options exist for this command.

The reason is that everything is optimized for hardware floating-point double precision. That's what you get when you set Digits to 15 or fewer or set the Matrix's datatype to float[8]. This is not Maple's doing. Your processor is optimized for it, the compilers are optimized for it, etc.

If M is your Matrix, then

Statistics:-StandardDeviation(M[1, ..]);
Statistics:-Histogram(M[1, ..]);

Here's an example of the type of recursion that Acer referred to in his comment. Once again, I apply it to a Cartesian product.

CartProdRecursive:= proc(L::list(list))
     local a,b;
     if nops(L) < 2 then [L]
     else thisproc([[seq(seq([op(a),b], a= L[1]), b= L[2])], L[3..-1][]])[]
     end if
end proc:
     
CartProdRecursive([[a,b], [1,2], [c,d]]);

This is a very inefficient way to generate a Cartesian product. Perhaps Acer has in mind another example where this recursion technique is competitive with other techniques.

Instead of "Modulus of Elasticity for Element i", use cat("Modulus of Elasticity for Element ", i).

Here's an example of a procedure that uses the parse statement to create another procedure with for loops nested to arbitrary depth. The goal of the latter procedure is to generate the Cartesian product of n lists, n being the argument of the first procedure. This is metaprogramming: writing a program that writes another program. It is a profoundly powerful technique which is much easier in Maple than in most other languages.

CartProdGen:= proc(n::posint)
local d; #depth
     parse(
          cat(
               "proc(", seq(cat("L",d,","), d= 1..n), "$)",
                    "local n:=0,",seq(cat("i",d,","), d= 1..n),
                    "R:= table()",
               ";",
                    seq(cat("for i", d, " in L", d, " do "), d= 1..n),               
                         "n:= n+1;",
                         "R[n]:= [", seq(cat("i",d,","), d= 1..n-1), "i", n, "]",
                    "end do " $ n, ";",
                    "convert(R, list)",
               "end proc;"
          )
     )
end proc:

Example of use:

CartProd3:= CartProdGen(3); #Generate the procedure



CartProd3([a,b], [c,d], [e,f]); #Use it

The two steps can be put together into a single procedure so that the generated procedure is immediately used:

CartProd:= (L::list(list))-> CartProdGen(nops(L))(L[]):

CartProd([[a,b], [1,2], [c,d]]);

There are many completely different very short procedures (several as short as two lines) for the Cartesian product of an arbitrary number of lists that don't use any metaprogramming (don't use the parse statement). They can be found by doing a MaplePrimes search on "Cartesian product of lists".

 

This is a very easy operation in Maple. Example:

R:= rand(0..9):
L:= ['R'() $ 100]:
nops(L);

     100

Unique:= {L[]};

CountUnique:= (L::list)-> nops({L[]}):
CountUnique(L);

     10

The primary way that a procedure returns a value is through a return statement, not through a variable declared evaln. The latter way is an obscure technique used for procedures that need to return something in addition to their primary return value. Indeed, it's hardly ever used now that procedures can return an expression sequence.

Max:= proc(L::list)
local i, Max:= -infinity;
     for i to nops(L) do
          if L[i] > Max then
               Max:= L[i]
          end if
     end do;
     return Max
end proc:

If the return statement is the last statement, then the word return can be omitted. So the above could simply have Max on the second-to-last line.

There's no syntactic reason why I used Max as both a local variable and a procedure name; it's just my style.

I avoided using max as the procedure name because it would conflict with Maple's built-in max. Overwriting the name of a built-in procedure is allowed, but that's another topic.

In Maple, Pi is spelled with a capital P. Your cotx will need to be changed to cot(x). You will need to supply numeric values for D1D2, a, and q before you can get a solution. The highest derivative of P in your ODEs is the first. Thus, you can only have three initial conditions, and you can't use D(P) as one of them.

Your particular solution, (i.e., your solution to the inhomogenoeus part) is correct. To get the general solution, you'll need inital conditions. In the code below I've used initial conditions that y, y', y'', and y''' are all 0 at t=0.

u:= exp(3*t)+3*exp(t):
ode:= diff(y(t),t$4) - 16*y(t) = diff(u,t) + u:
ICs:= seq((D@@k)(y)(0) = 0, k= 0..3):

dsolve({ode, ICs});

First 274 275 276 277 278 279 280 Last Page 276 of 395