acer

32363 Reputation

29 Badges

19 years, 332 days
Ontario, Canada

Social Networks and Content at Maplesoft.com

MaplePrimes Activity


These are replies submitted by acer

@Hyperian ...with the op command.

@jeffb No, the code I wrote has that op() fragment as it ought to be. op(1,A) should return two values, the row and column dimension of Matrix A.

The code I posted above works for me when I paste it -- as is -- into either Document or Worksheet of the Standard GUI of Maple versions 11.02, 12.02, 13.02, 14.01, 15.01, and 16.00 on MS-Windows.

What version and platform are you using? Can you save your worksheet, once you get the error, and upload it in a Comment here (using the green up-arrow in the Mapleprimes editing menubar)?

@jeffb No, the code I wrote has that op() fragment as it ought to be. op(1,A) should return two values, the row and column dimension of Matrix A.

The code I posted above works for me when I paste it -- as is -- into either Document or Worksheet of the Standard GUI of Maple versions 11.02, 12.02, 13.02, 14.01, 15.01, and 16.00 on MS-Windows.

What version and platform are you using? Can you save your worksheet, once you get the error, and upload it in a Comment here (using the green up-arrow in the Mapleprimes editing menubar)?

@jeffb You haven't shown your revised code, so we cannot tell the source of the error message.

mymatrix:=proc(A::Matrix,B::Matrix)
local i,j,q,C,numrowsA,numcolsA,numcolsB;
   numrowsA,numcolsA:=op(1,A);
   numcolsB:=op([1,2],B);
   C:=Matrix(numrowsA,numcolsB);
   for i from 1 to numrowsA do
      for j from 1 to numcolsB do
         for q from 1 to numcolsA do
            C[i,j]:=C[i,j] + A[i,q]*B[q,j];
         od;
      od;
   od;
   return C;
end proc:

x:=Matrix(3,2,symbol=X):
y:=Matrix(2,4,symbol=Y):

mymatrix(x,y) - x . y;

                                [0  0  0  0]
                                [          ]
                                [0  0  0  0]
                                [          ]
                                [0  0  0  0]

Should you add a check that the number of columns of A equals the number of rows of B?

If you've been instructed to not use any "built-in" routines then the spirit of that instruction is presumably to prevent you from simply using `.` or MatrixMatrixMultiply or something similar. You'll still have to use something to pick off the dimensions of A and B or else you'd have to pass those in as additional arguments in order to have the code get them right. I would guess that you probably are allowed to use LinearAlgebra:-Dimensions(), but if not then you might be allowed to use op() as above.

Don't blindly trust that code above: check it, via understanding.

@jeffb You haven't shown your revised code, so we cannot tell the source of the error message.

mymatrix:=proc(A::Matrix,B::Matrix)
local i,j,q,C,numrowsA,numcolsA,numcolsB;
   numrowsA,numcolsA:=op(1,A);
   numcolsB:=op([1,2],B);
   C:=Matrix(numrowsA,numcolsB);
   for i from 1 to numrowsA do
      for j from 1 to numcolsB do
         for q from 1 to numcolsA do
            C[i,j]:=C[i,j] + A[i,q]*B[q,j];
         od;
      od;
   od;
   return C;
end proc:

x:=Matrix(3,2,symbol=X):
y:=Matrix(2,4,symbol=Y):

mymatrix(x,y) - x . y;

                                [0  0  0  0]
                                [          ]
                                [0  0  0  0]
                                [          ]
                                [0  0  0  0]

Should you add a check that the number of columns of A equals the number of rows of B?

If you've been instructed to not use any "built-in" routines then the spirit of that instruction is presumably to prevent you from simply using `.` or MatrixMatrixMultiply or something similar. You'll still have to use something to pick off the dimensions of A and B or else you'd have to pass those in as additional arguments in order to have the code get them right. I would guess that you probably are allowed to use LinearAlgebra:-Dimensions(), but if not then you might be allowed to use op() as above.

Don't blindly trust that code above: check it, via understanding.

@andrewfortune Applying the ``() procedure to something makes a function call out of it, which prettyprints with round brackets. Thus, ``(17) gets printed as (17), which is useful. And `expand` undoes this, which is also useful.

So, ``(17)! gets printed just as (17)!

The operation subsindets(A,B,C) changes the expression A by substituting C(z) for all subexpressions z in A which are of type B.

For example,

expr:=(sin(2*x)+7)*exp(3*t);

                       expr := (sin(2 x) + 7) exp(3 t)

subsindets(expr,integer,z->z^2);

                          (sin(4 x) + 49) exp(9 t)

Here we have substituted each integer in `expr` by its square.

In simpler terms, what I did to my `T` to get my `Q` was to substitute for everything of a type matching z! with ``(z)!, where z could be anything.

You can `lprint` both `T` and `Q`, to see the difference.

You can also create your own Taylor series operator in Maple. And you can adjust it to suspend the factorial execution, as well.

restart:

taylor(sin(x),x=0,11); # The stock Library routine for this

                  1  3    1   5    1    7     1     9    / 11\
              x - - x  + --- x  - ---- x  + ------ x  + O\x  /
                  6      120      5040      362880            

convert(%,polynom);

                       1  3    1   5    1    7     1     9
                   x - - x  + --- x  - ---- x  + ------ x 
                       6      120      5040      362880   

t:=(e,x,x0,n)->add((x-x0)^i/i!*eval(diff(e,x$i),x=x0),i=1..n):
t(sin(x),x,0,9);

                       1  3    1   5    1    7     1     9
                   x - - x  + --- x  - ---- x  + ------ x 
                       6      120      5040      362880   

q:=(e,x,x0,n)->add((x-x0)^i/``(i)!*eval(diff(e,x$i),x=x0),i=1..n):
q(sin(x),x,0,9);

                            ((e,x,x0,n)->add((x-x0)^i/``(i)!*eval(diff(e,x$i),x=x0),i=1..n))(sin(x),x,0,9)

expand(%);

                       1  3    1   5    1    7     1     9
                   x - - x  + --- x  - ---- x  + ------ x 
                       6      120      5040      362880   

@andrewfortune Applying the ``() procedure to something makes a function call out of it, which prettyprints with round brackets. Thus, ``(17) gets printed as (17), which is useful. And `expand` undoes this, which is also useful.

So, ``(17)! gets printed just as (17)!

The operation subsindets(A,B,C) changes the expression A by substituting C(z) for all subexpressions z in A which are of type B.

For example,

expr:=(sin(2*x)+7)*exp(3*t);

                       expr := (sin(2 x) + 7) exp(3 t)

subsindets(expr,integer,z->z^2);

                          (sin(4 x) + 49) exp(9 t)

Here we have substituted each integer in `expr` by its square.

In simpler terms, what I did to my `T` to get my `Q` was to substitute for everything of a type matching z! with ``(z)!, where z could be anything.

You can `lprint` both `T` and `Q`, to see the difference.

You can also create your own Taylor series operator in Maple. And you can adjust it to suspend the factorial execution, as well.

restart:

taylor(sin(x),x=0,11); # The stock Library routine for this

                  1  3    1   5    1    7     1     9    / 11\
              x - - x  + --- x  - ---- x  + ------ x  + O\x  /
                  6      120      5040      362880            

convert(%,polynom);

                       1  3    1   5    1    7     1     9
                   x - - x  + --- x  - ---- x  + ------ x 
                       6      120      5040      362880   

t:=(e,x,x0,n)->add((x-x0)^i/i!*eval(diff(e,x$i),x=x0),i=1..n):
t(sin(x),x,0,9);

                       1  3    1   5    1    7     1     9
                   x - - x  + --- x  - ---- x  + ------ x 
                       6      120      5040      362880   

q:=(e,x,x0,n)->add((x-x0)^i/``(i)!*eval(diff(e,x$i),x=x0),i=1..n):
q(sin(x),x,0,9);

                            ((e,x,x0,n)->add((x-x0)^i/``(i)!*eval(diff(e,x$i),x=x0),i=1..n))(sin(x),x,0,9)

expand(%);

                       1  3    1   5    1    7     1     9
                   x - - x  + --- x  - ---- x  + ------ x 
                       6      120      5040      362880   

It turns out that CodeGeneration[C] does handle piecewise, but only if the optimize option is supplied. (I'll submit a bug report, that it should be handled by default.)

restart:

with(CodeGeneration):
with(LanguageDefinition):

myp:=proc(x::numeric) local result::numeric;
     result:=piecewise(x>3,3*x,x>2,2*x,x>1,1*x,0);
end proc;

         myp := proc(x::numeric)
         local result::numeric;
           result := piecewise(3 < x, 3*x, 2 < x, 2*x, 1 < x, x, 0)
         end proc;

Translate(myp, language="C", optimize);

double myp (double x)
{
  double result;
  double s1;
  if (0.3e1 < x)
    s1 = 0.3e1 * x;
  else if (0.2e1 < x)
    s1 = 0.2e1 * x;
  else if (0.1e1 < x)
    s1 = x;
  else
    s1 = 0.0e0;
  result = s1;
  return(result);
}

As you can see, piecewise is handled above by translation to a separate if(){..} block, with assignment to an introduced temporary variable. That temporary is subsequently used wherever the piecewise call existed in the Maple procedure. And the temporary is declared. Nice and automatic. So that might suffice for your use of piecewise.

You also asked how you could both introduce and declare such temporary variables in your own extensions (if I understand you rightly). Continuing on in the same Maple session from above, here are some ideas along those lines. An unassigned global name is generated. The myp procedure is put into inert form, to which the new local variable is added. And then that altered inert form is turned back into an actual procedure. As an illustration, I used a modified version of your original extension to handle piecewise. This all produces something close to acceptable. The only snag is that the assignment statement,

result = temporary_variable;

is out of place! It lies before the piecewise translation block. I don't yet see how to repair that in the method.

LanguageDefinition:-Define("NewC", extend="C",
    AddFunction("piecewise", anything::numeric,
        proc()
            global T;
            local i, t;
            t:=convert(T,string);
            Printer:-Print(t,";\n");
            Printer:-Print("  if (",_passed[1],
                           ")\n    { ",t," = ",_passed[2],"; }\n");
            for i from 3 to _npassed-2 by 2 do
                Printer:-Print("  else if (",_passed[i],")\n    { ",
                               t," = ",_passed[i+1],"; }\n");
            end do;
            Printer:-Print("  else { ",t," = ",_passed[_npassed],"; }");
        end proc,
    numeric=double)
):

T:=`tools/genglobal`('s'):

newmyp := FromInert(subsindets(ToInert(eval(myp)),'specfunc(anything,_Inert_LOCALSEQ)',
           z->_Inert_LOCALSEQ(op(z),
                              _Inert_DCOLON(_Inert_NAME(convert(T,string)),
                                            _Inert_NAME("numeric",
                                               _Inert_ATTRIBUTE(_Inert_NAME("protected",
                                               _Inert_ATTRIBUTE(_Inert_NAME("protected")
          ))))))));

Translate(newmyp, language="NewC");
         newmyp := proc(x::numeric)
         local result::numeric, s::numeric;
           result := piecewise(3 < x, 3*x, 2 < x, 2*x, 1 < x, x, 0)
         end proc;

double newmyp (double x)
{
  double result;
  double s;
  result = s;
  if (0.3e1 < x)
    { s = 0.3e1 * x; }
  else if (0.2e1 < x)
    { s = 0.2e1 * x; }
  else if (0.1e1 < x)
    { s = x; }
  else { s = 0; };
  return(result);

If you rerun the last three statements above (from the assignment to T, through to the Translate call) then you should see a new temp variable used, such as s0. And then s1 if repeated yet again. And so on.

Perhaps this will give you some more ideas to work with.

acer

It turns out that CodeGeneration[C] does handle piecewise, but only if the optimize option is supplied. (I'll submit a bug report, that it should be handled by default.)

restart:

with(CodeGeneration):
with(LanguageDefinition):

myp:=proc(x::numeric) local result::numeric;
     result:=piecewise(x>3,3*x,x>2,2*x,x>1,1*x,0);
end proc;

         myp := proc(x::numeric)
         local result::numeric;
           result := piecewise(3 < x, 3*x, 2 < x, 2*x, 1 < x, x, 0)
         end proc;

Translate(myp, language="C", optimize);

double myp (double x)
{
  double result;
  double s1;
  if (0.3e1 < x)
    s1 = 0.3e1 * x;
  else if (0.2e1 < x)
    s1 = 0.2e1 * x;
  else if (0.1e1 < x)
    s1 = x;
  else
    s1 = 0.0e0;
  result = s1;
  return(result);
}

As you can see, piecewise is handled above by translation to a separate if(){..} block, with assignment to an introduced temporary variable. That temporary is subsequently used wherever the piecewise call existed in the Maple procedure. And the temporary is declared. Nice and automatic. So that might suffice for your use of piecewise.

You also asked how you could both introduce and declare such temporary variables in your own extensions (if I understand you rightly). Continuing on in the same Maple session from above, here are some ideas along those lines. An unassigned global name is generated. The myp procedure is put into inert form, to which the new local variable is added. And then that altered inert form is turned back into an actual procedure. As an illustration, I used a modified version of your original extension to handle piecewise. This all produces something close to acceptable. The only snag is that the assignment statement,

result = temporary_variable;

is out of place! It lies before the piecewise translation block. I don't yet see how to repair that in the method.

LanguageDefinition:-Define("NewC", extend="C",
    AddFunction("piecewise", anything::numeric,
        proc()
            global T;
            local i, t;
            t:=convert(T,string);
            Printer:-Print(t,";\n");
            Printer:-Print("  if (",_passed[1],
                           ")\n    { ",t," = ",_passed[2],"; }\n");
            for i from 3 to _npassed-2 by 2 do
                Printer:-Print("  else if (",_passed[i],")\n    { ",
                               t," = ",_passed[i+1],"; }\n");
            end do;
            Printer:-Print("  else { ",t," = ",_passed[_npassed],"; }");
        end proc,
    numeric=double)
):

T:=`tools/genglobal`('s'):

newmyp := FromInert(subsindets(ToInert(eval(myp)),'specfunc(anything,_Inert_LOCALSEQ)',
           z->_Inert_LOCALSEQ(op(z),
                              _Inert_DCOLON(_Inert_NAME(convert(T,string)),
                                            _Inert_NAME("numeric",
                                               _Inert_ATTRIBUTE(_Inert_NAME("protected",
                                               _Inert_ATTRIBUTE(_Inert_NAME("protected")
          ))))))));

Translate(newmyp, language="NewC");
         newmyp := proc(x::numeric)
         local result::numeric, s::numeric;
           result := piecewise(3 < x, 3*x, 2 < x, 2*x, 1 < x, x, 0)
         end proc;

double newmyp (double x)
{
  double result;
  double s;
  result = s;
  if (0.3e1 < x)
    { s = 0.3e1 * x; }
  else if (0.2e1 < x)
    { s = 0.2e1 * x; }
  else if (0.1e1 < x)
    { s = x; }
  else { s = 0; };
  return(result);

If you rerun the last three statements above (from the assignment to T, through to the Translate call) then you should see a new temp variable used, such as s0. And then s1 if repeated yet again. And so on.

Perhaps this will give you some more ideas to work with.

acer

@asghar 

palin:=proc(T::list)
local i, n;
   n := nops(T);
   for i from 1 to n/2 do
      if T[i] <> T[n-i+1] then
         return false;
      end if;
   end do;
   return true;
end proc:

@asghar 

palin:=proc(T::list)
local i, n;
   n := nops(T);
   for i from 1 to n/2 do
      if T[i] <> T[n-i+1] then
         return false;
      end if;
   end do;
   return true;
end proc:

Thanks for the interesting read.

I wonder whether the quality of the embedded images could be improved, so that they are a bit sharper. If you'd like to post any Maple code that you might have used to generate them then it might be possible to alter the method. (...it looks like fun, but it'd be easier to not have to start from scratch on it.)

acer

@serena88 The procedure is returning the last "result" that it computes, from its last statement.

You can have a procedure return a sequence of results. Like so,

restart:
makeEOM:=proc(elenum)
local i, node, nodes, L, E0, E0M,E2,E2M;
   nodes:=elenum*2+1:
   L:=evalf((Pi*2)/(elenum*2)):
   E0:=Matrix([[L/3,2*L/3,L/3],[2*L/3,11*L/15,2*L/3],[L/11,2*L/3,L/110]]):
   E2:=Matrix([[L/13,2*L/13,L/13],[2*L/3,11*L/5,2*L/3],[L/11,2*L/13,L/11]]):   
   E0M:=Matrix(nodes);
   E2M:=Matrix(nodes);
   for i from 1 to elenum do
      node:=(2*(i-1))+1;
      E0M[node..node+2,node..node+2]:=E0M[node..node+2,node..node+2]+E0;
      E2M[node..node+2,node..node+2]:=E2M[node..node+2,node..node+2]+E2;
   end do:
   E0M, E2M;
end proc:

makeEOM(2); # returns a sequence of the two result Matrices

You can also use Maple's ability to do multiple assignments simultaneously (ie., concurrently),

e0m[2],e2m[2] := makeEOM(2);

And, once any pair are saved in the tables e0m and e2m, you could access them seperately,

e2m[2];
e0m[2];

@serena88 The procedure is returning the last "result" that it computes, from its last statement.

You can have a procedure return a sequence of results. Like so,

restart:
makeEOM:=proc(elenum)
local i, node, nodes, L, E0, E0M,E2,E2M;
   nodes:=elenum*2+1:
   L:=evalf((Pi*2)/(elenum*2)):
   E0:=Matrix([[L/3,2*L/3,L/3],[2*L/3,11*L/15,2*L/3],[L/11,2*L/3,L/110]]):
   E2:=Matrix([[L/13,2*L/13,L/13],[2*L/3,11*L/5,2*L/3],[L/11,2*L/13,L/11]]):   
   E0M:=Matrix(nodes);
   E2M:=Matrix(nodes);
   for i from 1 to elenum do
      node:=(2*(i-1))+1;
      E0M[node..node+2,node..node+2]:=E0M[node..node+2,node..node+2]+E0;
      E2M[node..node+2,node..node+2]:=E2M[node..node+2,node..node+2]+E2;
   end do:
   E0M, E2M;
end proc:

makeEOM(2); # returns a sequence of the two result Matrices

You can also use Maple's ability to do multiple assignments simultaneously (ie., concurrently),

e0m[2],e2m[2] := makeEOM(2);

And, once any pair are saved in the tables e0m and e2m, you could access them seperately,

e2m[2];
e0m[2];

Note that .ind file extensions are old and have no longer been advocated (for many major releases, now). Unfortunately some relevent help-files have still mentioned then in quite recent releases.

Basically, many years ago usual to have a pair of files that went together, with filename extensions .lib and .ind

But the modern way to use Maple Library archives is to have just the single file, with filename extension .mla

acer

First 408 409 410 411 412 413 414 Last Page 410 of 592