acer

32405 Reputation

29 Badges

19 years, 350 days
Ontario, Canada

Social Networks and Content at Maplesoft.com

MaplePrimes Activity


These are answers submitted by acer

There are several t-values at which abs(u2) tends to infinity with x=0. For example, EllipticK(1/2)/2.

You can fsolve for the six t-values in t=-5..5, for x=0.

The attachment shows how Optimization:-Maximize can be used get some approximate values out, hence to illustrate/hint at that.

It also shows fsolve (and solve, for one exact root) acting on the denominator.

plot_ac.mw

Why would you have thought that? Please explain your thinking.

Take x=Pi/4, and take its sin value.  Now take x=2*Pi+Pi/4, and take its sin value. You should get sqrt(2)/2 or approximately .707 for both.

Now consider how to compute arcsin(sin(2*Pi+Pi/4)).

Do you think that the result ought to be 2*Pi+Pi/4? The arcsin command is just going to recieve sqrt(2)/2 from being passed sin(2*Pi+Pi/4).

Here's the kicker: how do you expect arcsin to know whether the sqrt(2)/2 it receives came from sin(2*Pi+Pi/4) or sin(Pi/4)?

You might review some of the basic concepts of trig functions and their inverses -- paying attention to the restricted ranges of the inverse trig functions.

simplify(arcsin(sin(x))) assuming -Pi/2<=x, x<=Pi/2;

         x

sin(arcsin(x));

         x

There are several ways to correct your use of NLPSolve.

Download 4.6_ac.mw

[edit] Your code numerically computes a minimum of an abs call, at a discrete number of N points. You could also plot the smooth curve of the continuous zero-crossing. (Again, there are several ways; I show three ways in the following attachment, one of them using implicitplot.)  4.6_acc.mw
Here is the overlay of that with your 10-point plot:

Even if I "optimize" the size in stored memory of the plotted 2D polygons, the 3D animation can still be quite a burden on GUI resources.

Download IdeaVolume_ac.mw

By "optimizing" the 2D polygons I mean ensuring that each non-empty-area POLYGONS substructure contains only data for the 4 corner points (and not more, ugh), and that the edges of the polygons arise from its style and not from unnecessary line segments. All the subsindets stuff in the attached worksheet is there to try and keep each frame smaller in memory. And the resolution of the extrusion can (reasonably) be kept smaller for smaller rotation, by having it be a function of the angle.

Hard on the GUI. Perform manual rotation at your own risk; I suggest bumping down the partition and frames numbers, then rotating to taste, then reverting and relying on plot-persistence to retain the orientation.  Programmatically specified orientation in animations is a mess.

@zenterix It should not be "obvious" (your word) to you that the two might produce the same plot, since the inputs are not similar at all.

In the example, plot(i, i=1..5), the first argument is a continuous function of i.

In your second example, plot(l[i], i=1..5), the first argument is a list reference which only produces values at a discrete set of integer values.

There are various ways to infom the plot command to sample the second example's first argument at only a fixed number of positive integer values of the independent variable i. But your second example makes use of no such option. The failure is not the fault of the plot command.

You could also re-use your existing code, with a caveat:
It's not clear what you want to happen at the transition. I'm not sure whether you want either, none, or both of the animations to show at t=0. You could change the total number of frames to the odd number 141, say, to get either at t=0 (depending on a strict vs nonstrict inequality). You could also modify the `if` (nesting it, say) to display both at t=0, though I'd guess you might not want that.

(I'm supposing that you would not want to merge two separate animations which both had a t=0 frame.)

restart

DBG> quit

r1 := .35; m := 626; g := -9.807; u0 := -20; v0 := -20; x0 := 0; z0 := 15
omega0 := -24
J := (2/5)*m*r1^2

"vx(t):=t*2+15:"

"vz(t):=t*2+15:"

x1 := int(vx(t), t)

z1 := int(vz(t), t)

eqx1 := m*(diff(u(t), t)) = 0.; eqz1 := m*(diff(v(t), t)) = m*g

eqx0 := diff(x(t), t) = u(t); eqz0 := diff(z(t), t) = v(t)

eqr1 := J*(diff(omega(t), t)) = 5000*sin(t)

with(plots)

ini := x(0) = x0, u(0) = u0, z(0) = z0, v(0) = v0, omega(0) = omega0

sol1 := dsolve({eqr1, eqx0, eqx1, eqz0, eqz1, ini}, {omega(t), u(t), v(t), x(t), z(t)}, type = numeric, output = listprocedure)

p1 := odeplot(sol1, [[x(t), z(t)]], 0 .. 1, color = black, linestyle = dot)

t from 0 to 1

 

F1 := proc (tau) local pos, rot, j, cols; cols := [red, blue, red, blue]; if type(tau, numeric) then pos := [(eval(x(t), sol1))(tau), (eval(z(t), sol1))(tau)]; rot := (eval(omega(t), sol1))(tau); return plottools:-rotate(plots:-display([seq(plottools:-sector(pos, 1, (1/2)*(j-1)*Pi .. (1/2)*j*Pi, color = cols[j]), j = 1 .. 4)]), rot, pos) else return 'thisproc(tau)' end if end proc

x1 := animate(display, [F1(t), scaling = constrained], t = -1 .. 1, frames = 70)

t from -1 to 0

 

F2 := proc (tau) local pos, rot, j, cols; cols := [green, blue, green, blue]; if type(tau, numeric) then pos := [(eval(x(t)+1, sol1))(tau), (eval(z(t)+1, sol1))(tau)]; rot := (eval(omega(t), sol1))(tau); return plottools:-rotate(plots:-display([seq(plottools:-sector(pos, 1, (1/2)*(j-1)*Pi .. (1/2)*j*Pi, color = cols[j]), j = 1 .. 4)]), rot, pos) else return 'thisproc(tau)' end if end proc

x2 := animate(display, [F2(t), scaling = constrained], t = -1 .. 1, frames = 70)

animate(display, [`if`(t < 0, F2(t), F1(t)), scaling = constrained], t = -1 .. 1, frames = 140)

NULL

Download how_transition_ac.mw

The reason that it works in the procedure is that inside the procedure the (local) name x has been assigned using the set X, ie. lhs~(X). Once you get back to the top-level, outside your procedure, the global name x lacks that value.

Your subsequent top-level replacement could also be accomplished as (simpler, IMO),

    subsindets([dd], suffixed(x), ee -> ee(t))

I think that using globals is awkward, when not necessary. I prefer to use multiple return values, and have the substituted expressions be an additional return value. This would be my preferred approach.  elementwise_equal_ac.mw

Try this, for purely numeric integration:

evalf(Int(abs(1/(x - 2) + 0.5333 + 0.3333*x + 0.1333*x^2), x = -1 .. 1));

                         0.06041415825

By simplifying the integrand (which here sees that x>-1, x<1) before doing the symbolic integration the issue can be avoided.

value(simplify(Int(abs(1/(x - 2) + 0.5333 + 0.3333*x + 0.1333*x^2), x = -1 .. 1)));

                     0.06041419887

That symbolic integration of the simplified inert definite integral happens to produce a correct result and avoid the underlying symbolic problem, but I suggest you not rely on that technique, especially if you are willing to accept a solution with floats. Instead, I'd suggest you try to rely on the first approach I gave of performing purely numeric quadrature.

The following manipulation obtains the same erroneous negative result, and illustrates how it can go awry by, say, failing to split piecewise at every sign change in the integrand. (I used Maple 2022.2).

restart;
int(abs(1/(x - 2) + 0.5333 + 0.3333*x + 0.1333*x^2), x = -1 .. 1);

-0.5685437800e-1

restart;
Int(subsindets(convert(convert(abs(1/(x - 2) + 0.5333 + 0.3333*x + 0.1333*x^2),
                               rational,exact),Heaviside,x),specfunc(Heaviside),
               u->convert(u,piecewise)), x=-1..1);
H:=simplify(%);
value(%);
evalf(%);

Int(-1/(x-2)-5333/10000-(3333/10000)*x-(1333/10000)*x^2+2*piecewise(x <= 2, 0, 2 < x, 1)/(x-2)+(5333/5000)*piecewise(x <= 2, 0, 2 < x, 1)+(3333/5000)*piecewise(x <= 2, 0, 2 < x, 1)*x+(1333/5000)*piecewise(x <= 2, 0, 2 < x, 1)*x^2, x = -1 .. 1)

-(1/10000)*(Int((1333*x^3+667*x^2-1333*x-666)/(x-2), x = -1 .. 1))

-4333/3750+ln(3)

-0.56854378e-1

Download int_neg_ex0.mw

If you plot the integrand in H you can see that it has the wrong sign, for some values.

I will submit a bug report. [edit] It may already be fixed in the version under deveopment.

One way is to use an anonymous procedure.

If the operation involves a command that passes extra arguments at the end then your particular implementation of `&/` allows a terser solution.

restart;

 

`&/`:=()->args[-1](args[1],args[2..-2]):

 

0.76 &/ (u->convert(u,fraction))

19/25

0.76 &/ (fraction,convert)

19/25

(a*x+x*b) &/ simplify &/ (u->subs(a=2,b=3,u))

5*x

(a*x+x*b) &/ simplify &/ (u->eval(u,[a=2,b=3]))

5*x

(a*x+x*b) &/ simplify &/ ([a=2,b=3],eval)

5*x

Download infix_fun.mw

1) You could change the initial creation of A to,

   A := Matrix(11,11);

and then do your loop.

2) Or you could get rid of the loop altogether and create it as,

   A := Matrix(11,11,(i,j)->i+j-2);

3) Or you could just change the entry assigning line to,

   A(i,j) := i+j;

It happens because A2 is a Matrix, a mutable data structure.

The assignment inside your procedure makes A1 a reference to A. And Matrix A2 is not copied when it is passed in as an argument to the procedure call, so A is a reference to A2.

So your updates to entries of A1 are updates to entries of A, and thus are actually updates to entries of A2. This is part of something that is sometimes called in-place semantics.

If you don't want that behaviour then you can use copy semantics instead, by replacing the line that assigns to A1 as,

   A1 := copy(A);

Changing just that aspect of your example,

restart

diagonalize := proc (A) local A1; A1 := copy(A); A1(1, 1) := 0; A1(2, 2) := 0; A1(3, 3) := 0; return A1 end proc

A2 := Matrix([[-3, -.1, -.2], [.1, 7, -.3], [.3, -.2, 10]])

diagonalize(A2)

Matrix(%id = 36893628348005758484)

A2

Matrix(%id = 36893628348005757404)

Download d_ac.mw

In-place semantics allow for reduced memory use, by not creating a copy unless necessary. This can be a useful and convenient default for mutable data structures; it can gain efficiency for large examples that do not require the copy (because, say, they might not need the original data preserved).

@zenterix How about using ExportMatrix to export purely numeric data to files? You could compare the timing by using (or not) binary (Matlab) file formats supported by that command.

If there are headers (containing nonnumeric data) for the rows or columns then you could save those separately. For large amounts of float data I suspect that it'd be more efficienct to export/re-import without headers (datatype=float[8], say), as Matrix or Array (not DataFrame or anything fancy).

You could generate the filenames in the parent process, and pass one into each Grid process.

Here's how your stated target can be found using collect, as well as some alternative metrics.

I also show an alternative result, which scores better than your proposed target on all four metrics shown.

restart;

L := ee->[length(ee),`simplify/size/size`(ee),
          MmaTranslator:-Mma:-LeafCount(ee), codegen[':-cost'](ee)]:

 

expr := G1*P3 + G1*P5 + G1*P6 + G2*P3 + G2*P6 + G3*P2 + G3*P5 + G4*P2 + G4*P3 + G4*P5 + G4*P6 + G5*P2 + G5*P3 + G5*P5 + G5*P6 + G6*P3 + G6*P6 + G7*P2 + G7*P5 + G8*P2 + G8*P3 + G8*P5 + G8*P6;

G1*P3+G1*P5+G1*P6+G2*P3+G2*P6+G3*P2+G3*P5+G4*P2+G4*P3+G4*P5+G4*P6+G5*P2+G5*P3+G5*P5+G5*P6+G6*P3+G6*P6+G7*P2+G7*P5+G8*P2+G8*P3+G8*P5+G8*P6

L(expr);

[323, 138, 70, 22*additions+23*multiplications]

thaw(simplify(collect(expr,indets(expr,suffixed(P)),freeze)));

(P3+P6)*(G1+G2+G4+G5+G6+G8)+(G3+G4+G5+G7+G8)*P2+(G1+G3+G4+G5+G7+G8)*P5

L(%);

[134, 82, 29, 17*additions+3*multiplications]

thaw(simplify(collect(expr,[G1, P2, P5],freeze@simplify)));

(P2+P5)*(G3+G4+G5+G7+G8)+(P3+P5+P6)*G1+(P3+P6)*(G2+G4+G5+G6+G8)

L(%);

[123, 71, 27, 14*additions+3*multiplications]

Download crush_ex0b.mw

@zenterix 

If you keep/create your packages in the following pattern then the lib subdirectories get added to libname automatically upon relaunch.

  $(HOME)/maple/toolbox/mypackage/

where the .mla for that package is put in a subdirectory named lib.

You can also put the source under that directory.

And so all the source, along with the .mla, can be under that mypackage directory.

And similarly for mypackage2, mypackage3, etc.

In new Maple sessions the kernel will pick up the lib subdirectories for all such, and add them to libname.

The key here is putting them under this special location: whatever this returns,

  cat(kernelopts(homedir),"/maple/toolbox");

This approach removes the need to use any initialization file. Thus any tricky editing of an initialization file is wholly unnecessary.

And it lets you keep each package's source and .mla under its own directory. (Which you wanted, for github.)

The value of libname gets further augmented (in subsequent sessions) simply by adding another package in another such directory tree.

Side-note: You can also programatically create a self-installing file which unpacks any or all of .mla, .help, source, and build-scripts to the equivalent directory on someone else's machine. (This knows where to place these toolbox files regardless of operating system: Linux, MS-Windows, or OSX.)

This is the scheme Maple uses for its own add-on toolboxes. Why reinvent the wheel?

As documented on the procedure Help page, within a procedure a reference to a local gets only single level evaluation.

In contrast a declared global gets fully evaluated.

Here are a few notes:

restart;

gen := () -> 4.5:

p := proc()

  global g;
  local a,b,c;

  g := b;
  c := b;

  b := a;

  a := 'gen()';

  print( a, b, c, g );

end proc:


Inside the procedure p,
   a gets single level evaluation, obtaining its value,
      which is the unevaluated function call gen().
   b gets single level evaluation, obtaining just `a`
   c gets single level evaluation, obtaining just  `b`
   g gets fully evaluated, obtaining 4.5

p();

gen(), a, b, 4.5

restart;

gen := () -> 4.5:

g := b:
c := b:

b := a:

a := 'gen()':


At the top-level (ie. outside any procedure), these all
get fully evaluated.

a, b, c, g;

4.5, 4.5, 4.5, 4.5

The following mimics the kinds of evaluation that
occured within the call to procedure p. Compare
with the result above of calling p().

eval(a,1), eval(b,1), eval(c,1), g;

gen(), a, b, 4.5

Even at the top-level we can control the level of
evaluation, or perform full evaluation as usual.

eval(g,1), eval(g,2), eval(g,3), g;

b, a, gen(), 4.5

eval(c,1), eval(c,2), eval(c,3), c;

b, a, gen(), 4.5

Here's a tip for top-level programming:
Suppose we want to test whether sol gets assigned a
solution, or whether fsolve has returned unevaluated,
(since no solution is found).

sol := fsolve({x+y=0, sin(x)+sin(y)=3}, {x,y});

fsolve({x+y = 0, sin(x)+sin(y) = 3}, {x, y})

The following appears reasonable, but in fact this
top-level reference to sol induces a full evaluation of sol.
This makes fsolve get needlessly called again, which
is inefficient.

if op(0,sol) = fsolve then
  print("it returned unevaluated");
end if;

"it returned unevaluated"

The following gets the same test, but doesn't make
fsolve get called again. (You could trace(fsolve), or
run in the debugger, to see that this is so.)

if op(0,eval(sol,1)) = fsolve then
  print("it returned unevaluated");
end if;

"it returned unevaluated"

In contrast, the following code -- within a
procedure, with sol declared local -- makes
only the initial call to fsolve. There is no repeated,
(inefficient) attempt by fsolve during the if...then
test since the local named sol gets only single level
evaluation.

restart;
##trace(fsolve):
h := proc()
  local sol;
  sol := fsolve({x+y=0, sin(x)+sin(y)=3}, {x,y});
  if op(0,sol) = fsolve then
     print("it returned unevaluated");
   end if;
end proc:

h();

"it returned unevaluated"

 

Download local_eval_notes.mw

First 57 58 59 60 61 62 63 Last Page 59 of 336