pagan

5147 Reputation

23 Badges

17 years, 127 days

 

 

"A map that tried to pin down a sheep trail was just credible,

 but it was an optimistic map that tried to fix a the path made by the wind,

 or a path made across the grass by the shadow of flying birds."

                                                                 - _A Walk through H_, Peter Greenaway

 

MaplePrimes Activity


These are answers submitted by pagan

I don't see why it wouldn't work for you with a[i] and b[i] as indexed names.

a[1]:=[[1,2,3,4,5,6,7],[9,8,7,6,5,4,3],[4,5,4,5,4,5,4]]:
a[2]:=[[2,3,4,5,6,7,8],[8,7,6,5,4,3,2],[3,4,3,4,3,4,3]]:
a[3]:=[[3,4,5,6,7,8,9],[7,6,5,4,3,2,1],[2,3,2,3,2,3,2]]:

G:=(L,x,y)->[op(L[1..x-1]),L[y],op(L[x+1..y-1]),L[x],op(L[y+1..-1])]:

for i from 1 to 3 do
  b[i]:=map(G,a[i],4,6);
end do;

ps. Scott, he wanted to create new objects, where b[i] is a[i] with swapped 4th and 6th entries. He didn't just want to extract just those two entries (which would be simpler to do, 'natch.)

I suspect that you are likely using structures not best suited for your overall tasks, ie. lists instead of mutable Matrix & Vector.

a1:=Matrix([[1,2,3,4,5,6,7],[9,8,7,6,5,4,3],[4,5,4,5,4,5,4]]);

# one way
b1:=LinearAlgebra:-ColumnOperation(a1,[4,6]);

# alternatively
b1:=copy(a1):
b1[1..-1,4],b1[1..-1,6] := b1[1..-1,6],b1[1..-1,4]:
b1;

Why use lists of lists? And why use || to form the names (in other posts as well) instead of just a[i] and b[i]?

Anyway, if you really must...

a1:=[[1,2,3,4,5,6,7],[9,8,7,6,5,4,3],[4,5,4,5,4,5,4]];
G:=(L,x,y)->[op(L[1..x-1]),L[y],op(L[x+1..y-1]),L[x],op(L[y+1..-1])]:
map(G,a1,4,6);

Try telling Maple something about alpha.

> int(exp(-(alpha*x)^2),x=0..infinity) assuming alpha::real;
                                       1/2
                                     Pi
                                 -------------
                                         2 1/2
                                 2 (alpha )

You might find yourself wondering: how to convert to piecewise if the expression containing that `min` call is returned from some Maple Library routine which is outside your direct control (as far as making it return piecewise instead).

You could notice that this gets only part of it

convert(f(x,lambda),piecewise,lambda) assuming x>0;

And an assumption such as (x>0 or x<0), or just x<>0, fails to work.

Apart from manually freezing x*lambda, substituting, converting to piecewise, and then resubstituting/thawing, is there any easier was to get that particular conversion to piecewise without having to resort to frontend?

f:=(x,lambda)->min(x*lambda,0):

frontend(convert,[f(x,lambda),piecewise,x*lambda],[{'specfunc'('anything',min)},{}]);

diff(%,lambda);

Maple does issue a warning when you assign to name inside a proc body and without declaring it as local to the proc. In this case, Maple automatically declares the assigned name as a local. It does not do so when you access the name (without assigning), because that is a legal attempt at using Maple's lexical scoping functionality.

Have a look at ?mint and ?maplemint for checking and validating code.

> p:=proc(x);
> y:=z*x;
> end proc;
Warning, `y` is implicitly declared local to procedure `p`
p := proc(x) local y; y := z*x end proc
> z:='z': > p(5); 5 z > z:=17: > p(5); 85

Notice how no local z was implicitly declared above, b/c it was used but not assigned to.

A couple of pieces of friendly advice:

If a new last line of UpdateAllVelocoties() is inserted, as just NULL; then the proc won't return anything. That's ok since it acts inplace and will still work oj, but doing so might cut down on the noisy display (when you are ready for that, and past developing).

As Joe mentioned, there is a type-check on the third parameter of the proc. So what you pass must match.

I suggest not using the same names at the higher level as you do for the parameters. That is because it can lead you to mistakes. Maple supports lexical scoping (in its default interpreter, but not in all modes of operation). So it will let you reference variables from a higher level while inside the proc. But then you might make a mistake when you thought that you'd passed a variable when in fact you hadn't. Better to keep the names different. Eg, Vel outside and passed, and vel as the param in the proc declaration and inside the proc body.

Round brackets for Matrix/Vector/Array reference are kind of newish to Maple. They have some specific new uses. But if you don't want to get confused, or want backward compatibility with earlier versions (say, back to Maple 6), I would use square brackets unless you are deliberately growing the object

The following works for me. But so did you roiginal, as long as accel was actually a Matrix.

restart:

vel := Matrix(3, 241, datatype = float[8]):
accel:=Matrix(3, 241): # not used
step := 0.1:

vel[1, 1] := 5: vel[2, 1] := 95: vel[3, 1] := 3:

UpdateAllVelocities := proc (i, vel::Matrix, accel::Matrix, step);
vel[1, i] := vel[1, 1];
vel[2, i] := vel[2, 1];
vel[3, i] := vel[3, 1];
NULL; # acts inplace, so no need to see the last result
end proc:

for i from 1 to 241 do
UpdateAllVelocities(i, vel, accel, step);
end do;

vel[2,117], vel[3,199], vel[1,29];

interface(rtablesize=300):
vel; # looks right

In the original code, you are storing all of X[i], ics[i], q[i], p[i], etc, for each and every `i` value. Is that truly what you need?

It might be that Maple is getting short on memory because you are retaining too much symbolic stuff (formulae at each i) such as all entries of those tables, carried along through the whole session.

If you don't need them all, then why use an indexed (table) reference for assignment of each one? Why not use ics_last and ics_current, etc, having just  a pair for each variable at any given iteration through the loop? (You update the last one to be the current one, at the end or start of each major iteration. This would allow garbage collection of the unretained, old formulae from earlier iterations.)

And even if you really wanted to store the X[i] and ics[i], you don't really need to store q and p as well, do you? Maybe you don't need to save any of them. Or maybe you could just write the 1D formula of X[i] and ics[i] to a text file, instead of saving the table.

You can use try..catch for this. The essence is that you can catch errors (specific or general) and then handle such siutations and continue. Here is just one simple example along such lines.

f:=proc(n) 
  if irem(n,2)=1 then
   error "bad argument at some location";
  else g(i);
  end if;
end proc:

for i from 1 to 6 do
  try
     res:=f(i);
     print(res);
  catch "bad argument at":
     printf("problem at i=%a\n", i);
  end try;
end do:

Maybe an example will help. Compare these two plots' y-axes as produced in Maple's Standard GUI.

a, b := 0.00000, 0.00007:

plot(sin(x),x=a..b);

plot(sin(x),x=a..b,ytickmarks=[seq(t=sprintf("%2.2e",t),t=a..b, 0.00001)]);

You can use the angle-bracket shortcuts for this.

a:=<<1,2>|<3,4>>;
b:=<<5,6>|<7,8>>;
c:=<<9,10>|<11,12>>;
d:=<<13,14>|<15,16>>;

<<a|b>,<c|d>>;

Or you could use the Matrix() constructor.

Matrix([[a,b],[c,d]]);

By default, you only see the contents displayed for 10x10 and smaller Matrices when in the Standard GUI. Change this like so

interface(rtablesize=50):

Nice tto see John again.

Compare these to your original.

for i to 2 do
  equns[i] := sum(uvec[j]*('diff'(uvec[i], xvec[j])), 'j' = 1 .. 2);
end do;

for i to 2 do
  equns[i] := add(uvec[j]*(diff(uvec[i], xvec[j])), j = 1 .. 2);
end do;

Can you just use what is already directly available in LinearAlgebra?

with(LinearAlgebra):

A := `<|>`(`<,>`(6, 2, 1, 6, 8, 3),
     `<,>`(4, 3, 7, 1, 7, 2), `<,>`(3, 7, 2, 4, 3, 9)):

b := `<,>`(55, 37, 40, 33, 60, 75):

LinearAlgebra:-LeastSquares(A,b,method=SVD);

LinearAlgebra:-MatrixInverse(evalf(A),method='pseudo');

You can also do all that after infolevel[LinearAlgebra]:=1 to see some additional details.

Or do you want to do all the SVD work explictly (so as to re-use the SVD results and not have it done twice -- once for A^(-1) and once for X)?

u,s,v := SingularValues(evalf(A),output=[U,S,Vt]);

u,s,v := SingularValues(evalf(A),output=[U,S,Vt],'thin');

DiagonalMatrix(s[1..min(op(1,A))]);

The efficient re-use issue brings up a question: couldn't LeastSquares and MatrixInverse accept a list of svd results in lieu of Matrix A, similar to how LinearSolve and MatrixInverse and ConditionNumber accept lists of lu or qr decompositions?

It's not all-powerful, but you can get something out of the noncommuting &* operator.

> restart:
> expand( (1-B) * (1+A+A*B) ); # commutative `*`, not what you want.
                                              2
                               1 + A - B - A B
 
> alias( Id = &*() ):
> expand( (Id-B) &* (Id+A+A&*B) );
                Id + A + (A &* B) - B - (B &* A) - &*(B, A, B)

For some tasks, evalm can also help.

With coefficients in such a large range, from 10^0 through to 10^26, I would consider whether the working precision would need to be raised from its default of 10, so as to avoid roundoff getting in the way.

> restart:

> fsolve({(1.+x[1])*exp(x[1]) = 7.505833908*10^26,
>  (1.+x[2])*exp(x[2]) = 3.000809640*10^12},{x[1], x[2]});
                                               27
fsolve({(1. + x[1]) exp(x[1]) = 0.7505833908 10  ,
 
                                           13
    (1. + x[2]) exp(x[2]) = 0.3000809640 10  }, {x[1], x[2]})
 
> Digits:=30:

> fsolve({(1.+x[1])*exp(x[1]) = 7.505833908*10^26,
> (1.+x[2])*exp(x[2]) = 3.000809640*10^12},{x[1], x[2]});
{x[1] = 57.8086048059798635210542056047,
 
    x[2] = 25.4544778107959698119898419056}

And, in completely restarted sessions, I saw a result starting at Digits:=12. But, YMMV.

Are you supposed to write a program which shuffles or merges the entries of Array(s) on the basis of various comparisons (eg. is(a<b))? Could you implement one of these algorithms, based on pseudocode such as here for example?

If so, the following wouldn't be in the spirit of the question and so wouldn't be ok. It's not particularly efficient either, since it creates an equation for each entry. But it's short and a bit of casual fun. Of course, it relies on Digits being set high "enough". It also relies on kernelopts(setsort), for which it needs Maple 12, 13, or 14. Use of elementwise ~ can be altered to use of `map` in Maple 12. Of course, reversing its result to be big to small instead of small to big is trivial.

> numsorter:=Q->rhs~([op({seq(evalf(x)=x,x=_passed)})]):

> numsorter(Pi,-Pi,sqrt(11),17/5,-4/3,0.1,surd(17,3));
                                     (1/3)        1/2
                  [-Pi, -4/3, 0.1, 17     , Pi, 11   , 17/5]
# large to small, including sign
numsorter:=Q->(rhs)~([op({seq(-evalf(x)=x,x=_passed)})]):

# or by reverse magnitude
numsorter:=Q->(rhs)~([op({seq(-abs(evalf(x))=x,x=_passed)})]):
First 32 33 34 35 36 37 38 Last Page 34 of 48