4 Symbolic manipulation, expression filtering, structured types

4.1 on maple data types
4.2 how to extract elements from a list based on some selection?
4.3 how to test if all elements of a matrix are integers?
4.4 How to select terms with sqrt or radical
4.5 How to find all csgn() and replace them by 1
4.6 How to find symbols inside csgn() in an expression?
4.7 How to replace all abs(expr) by expr
4.8 How to obtain list of all occurances of some function in an expression?
4.9 How to replace \(\ln (|x|)\) with \(\ln (x)\) in an expression?
4.10 How to find all signum functions in expression and simplify it?
4.11 How to replace all signum functions in expression by 1?
4.12 How to find if some function is present in an expression
4.13 How to find all functions in an expression?
4.14 find all functions except builtin math functions
4.15 How to obtain a list of all arguments of function?
4.16 Find functions whose first argument is \(z\)
4.17 Find functions whose second argument is \(t\)?
4.18 How to use select with own type to find subexpressions?
4.19 How to write structured types to match some expressions?
4.20 select only indexed variables from an expression
4.21 Given an expression, how to find all variables and functions in it?
4.22 How to check if an expression is integer, when it has symbols in it?
4.23 How to find parameters such as \(\pi \) in an expression?
4.24 How to find all derivatives \(y'(x)\) in an expression?
4.25 How combine log terms?
4.26 Find position in a list of items that are not numeric
4.27 How to change \(\arctan (y,x)\) to \(\arctan \left (\genfrac {}{}{}{}{y}{x}\right )\) in an expression
4.28 How to find all symbols that represent variables in an expression?
4.29 How to change first argument of function?
4.30 How to change last argument of function?
4.31 How to remove last argument of function?
4.32 How to find a pattern inside an expression
4.33 How to find parts of a Sum?
4.34 find if sequence or list is inside another and the indecies
4.35 find if some type inside some expression and its location
4.36 How to replace generic function inside derivative?
4.37 Examples how to match types
4.38 On the order of terms when using indents

4.1 on maple data types

See http://www.maplesoft.com/applications/view.aspx?SID=1533&view=html&L=G

4.2 how to extract elements from a list based on some selection?

use select. For example

>restart; 
>my_list:=[1,3.4,3+I,5]; 
>select(x->evalb(Im(x)=0),my_list); 
        [1, 3.4, 5]
 

4.3 how to test if all elements of a matrix are integers?

restart; 
m:=Matrix( [[1.3,2,3],[3,4,4] ]); 
matrixTestQ := proc(m::Matrix) 
 
    local r,c,i,j; 
 
    (r,c):=LinearAlgebra[Dimensions](m); 
    for i from 1 to r do 
       for j from 1 to c do 
           if( not evalb( whattype(m[i,j]) = integer) )  then 
               return(false); 
            end if; 
        end do; 
    end do; 
 
    return true; 
end proc; 
 
>matrixTestQ(m); 
 
               false
 

I am sure there is a better way than the above. Need to find out.

4.4 How to select terms with sqrt or radical

Given

\[ 3+x +\sqrt {-4 a c +b^{2}}+\sin \left (y \right )+x^{3} \sqrt {39}+\sqrt {\cos }x \]

Find terms that are sqrt. Use indets

restart; 
expr_with_radical:= 3+x+sqrt(b^2-4*a*c)+sin(y)+x^3*sqrt(39)+sqrt(cos(x));| 
indets(expr_with_radical, algebraic^fraction)
 

\( \{ \sqrt {39}, \sqrt {-4 a c +b^{2}}, \sqrt {\cos }x \} \)

Alternative is to use type radical

restart; 
expr_with_radical:= 3+x+sqrt(b^2-4*a*c)+sin(y)+x^3*sqrt(39)+sqrt(cos(x));| 
indets(expr_with_radical, radical)
                                                                                    
                                                                                    
 

\( \{ \sqrt {39}, \sqrt {-4 a c +b^{2}}, \sqrt {\cos }x \} \)

4.5 How to find all csgn() and replace them by 1

I wanted to simplify an expression which could have csgn() in it, and find all the arguments.

\[ \frac {1+\mathrm {csgn} \left (a \right ) a}{3 \mathrm {csgn} \left (b \right ) b} \]

One way is

restart; 
expr:=(1+csgn(a)*a)/(3*csgn(b)*b): 
expr:=subsindets(expr,'specfunc( anything, csgn )',f->1);
 
\[ \frac {1+a}{3 b} \]

4.6 How to find symbols inside csgn() in an expression?

Given  sol:=1/2*2^(1/2)*csgn(x)*x*csgn(y);  how to find all symbols inside csgn which will be \(x,y\) in this case?

restart; 
sol:=1/2*2^(1/2)*csgn(x)*x*csgn(y); 
indets(sol,'specfunc( anything, csgn )'); 
vars:=subsindets(%,'specfunc( anything, csgn )',f->op(f))
 

Gives {x, y}

Now if we want to simplify the above solution by assuming that all variables inside vars are positive, how to do that?

restart; 
sol:=1/2*2^(1/2)*csgn(x)*x*csgn(y); 
indets(sol,'specfunc( anything, csgn )'); 
vars:=subsindets(%,'specfunc( anything, csgn )',f->op(f)); 
simplify(sol) assuming op(map2(`<`,0,vars))
 

Gives \(\frac {\sqrt {2}\, x}{2}\). Notice in the above the use of op(map2(`<`,0,vars)), this will generate the sequence 0 < x, 0 < y automatically. op is needed otherwise the result will be {0 < x, 0 < y} which will give syntax error when passed to assuming

Ofcourse, it would have been also possible to just write

simplify(sol) assuming positive;
 

And get the same result. But sometimes we might want to specify which variables are to be assumed positive and not all of them at once in the expression.

4.7 How to replace all abs(expr) by expr

I wanted to replace  |expr| by (expr)

One way is

restart; 
expr:=u(x) = _C1*exp(-3*x^(1/3)*sqrt(c))*(3*x^(1/3)*sqrt(c) + 1) + _C2*exp(3*x^(1/3)*sqrt(c))*abs(-1 + 3*x^(1/3)*sqrt(c));
 
\[ u \left (x \right ) = \textit {\_C1} \,{\mathrm e}^{-3 x^{\frac {1}{3}} \sqrt {c}} \left (3 x^{\frac {1}{3}} \sqrt {c}+1\right )+\textit {\_C2} \,{\mathrm e}^{3 x^{\frac {1}{3}} \sqrt {c}} {| -1+3 x^{\frac {1}{3}} \sqrt {c}|} \]
expr:=subsindets(expr,'specfunc( anything, abs )',f->op(f));
 
\[ u \left (x \right ) = \textit {\_C1} \,{\mathrm e}^{-3 x^{\frac {1}{3}} \sqrt {c}} \left (3 x^{\frac {1}{3}} \sqrt {c}+1\right )+\textit {\_C2} \,{\mathrm e}^{3 x^{\frac {1}{3}} \sqrt {c}} \left (-1+3 x^{\frac {1}{3}} \sqrt {c}\right ) \]

4.8 How to obtain list of all occurances of some function in an expression?

For an example, How to find list of all \(\ln \) functions in this expression?

\[ \ln \left ({| x +1|}\right )+2 x \ln \left (x \right )+\sin \left (x \right ) \]
restart; 
expr:=ln(abs(x+1))+2*x*ln(x)+sin(x); 
tmp := indets(expr,'specfunc(anything,ln)'); 
 
          #   tmp := {ln(x), ln(abs(x + 1))}
 

To pick only \(\ln \) functions which has \(abs\) inside them anywhere, replace the above with

restart; 
expr:=ln(abs(x+1))+2*x*ln(x)+sin(x); 
lis:=indets(expr,'specfunc(anything,ln)'); 
select(Z->has(Z,abs),lis) 
 
          #   tmp := {ln(abs(x + 1))}
 

Or, better alternative to the above is

restart; 
expr:=ln(abs(x+1))+2*x*ln(x)+sin(x); 
indets(expr,'specfunc( satisfies(u->has(u,abs)) ,ln  )'); 
 
          #   tmp := {ln(abs(x + 1))}
 

4.9 How to replace \(\ln (|x|)\) with \(\ln (x)\) in an expression?

Given

\[ \sin \left (x \right )+\ln \left ({| x |}\right )+\ln \left (x +\frac {{| y |}}{\sqrt {{| x +3|}}}\right )+\ln \left (x^{3}\right )+\cos \left ({| x |}\right ) \]

How to remove the absolute, the ones only inside each \(\ln \) in the above expression?

restart; 
expr:=sin(x)+ln(abs(x))+ln(x+abs(y)/sqrt(abs(x+3)))+ln(x^3)+cos(abs(x)); 
expr:=evalindets(expr,'specfunc(ln)',f->evalindets(f,'specfunc(abs)',f->op(1,f))) 
 
#   sin(x) + ln(x) + ln(x + y/sqrt(x + 3)) + ln(x^3) + cos(abs(x))
 
\[ \sin \left (x \right )+\ln \left (x \right )+\ln \left (x +\frac {y}{\sqrt {x +3}}\right )+\ln \left (x^{3}\right )+\cos \left ({| x |}\right ) \]

4.10 How to find all signum functions in expression and simplify it?

Given

\[ -\frac {\left (\ln \left (\frac {\left (b +\sqrt {b^{2}+y \left (x \right )^{2}}\, \mathrm {signum}\left (b \right )\right ) b}{y \left (x \right )}\right )+\ln \left (2\right )\right ) \mathrm {signum}\left (b \right )}{b} = \mathit {\_C1} +\frac {-\ln \left (a \right )+\ln \left (x \right )-\ln \left (a +\sqrt {a^{2}+x^{2}}\, \mathrm {signum}\left (a \right )\right )-\ln \left (2\right )}{{| a |}} \]

How to find all arguments of signum and simplify the above by assuming they are all positive?

restart; 
expr:=-(ln((b + sqrt(b^2 + y(x)^2)*signum(b))*b/y(x)) + ln(2))*signum(b)/b = _C1 + (-ln(a) + ln(x) - ln(a + sqrt(a^2 + x^2)*signum(a)) - ln(2))/abs(a); 
lis:=indets(expr,'specfunc(anything,signum)'); 
assum:=convert(map(x->op(1,x)>0,lis),list); 
simplify(expr,assume=assum);
 
\[ \frac {-\ln \left (b \right )-\ln \left (\frac {b +\sqrt {b^{2}+y \left (x \right )^{2}}}{y \left (x \right )}\right )-\ln \left (2\right )}{b} = \frac {\mathit {\_C1} a -\ln \left (a \right )-\ln \left (a +\sqrt {a^{2}+x^{2}}\right )+\ln \left (x \right )-\ln \left (2\right )}{a} \]

4.11 How to replace all signum functions in expression by 1?

Given

\[ -\frac {\left (\ln \left (\frac {\left (b +\sqrt {b^{2}+y \left (x \right )^{2}}\, \mathrm {signum}\left (b \right )\right ) b}{y \left (x \right )}\right )+\ln \left (2\right )\right ) \mathrm {signum}\left (b \right )}{b} = \mathit {\_C1} +\frac {-\ln \left (a \right )+\ln \left (x \right )-\ln \left (a +\sqrt {a^{2}+x^{2}}\, \mathrm {signum}\left (a \right )\right )-\ln \left (2\right )}{{| a |}} \]

How to replace all signum by 1?

restart; 
expr:=-(ln((b + sqrt(b^2 + y(x)^2)*signum(b))*b/y(x)) + ln(2))*signum(b)/b = _C1 + (-ln(a) + ln(x) - ln(a + sqrt(a^2 + x^2)*signum(a)) - ln(2))/abs(a); 
evalindets(expr, 'specfunc(anything,signum)', f -> 1);
 
\[ -\frac {\ln \left (\frac {\left (b +\sqrt {b^{2}+y \left (x \right )^{2}}\right ) b}{y \left (x \right )}\right )+\ln \left (2\right )}{b} = \textit {\_C1} +\frac {-\ln \left (a \right )+\ln \left (x \right )-\ln \left (a +\sqrt {a^{2}+x^{2}}\right )-\ln \left (2\right )}{{| a |}} \]

4.12 How to find if some function is present in an expression

Given expression \(3 \sin \left (x \right )+t +3 f \left (x , t\right ) t +g \left (x , t\right )\) find if it contains function \(f()\).

Use indets with specfunc(f)

restart; 
expr := 3*sin(x)+t+3*f(x,t)*t+g(x,t); 
res  := indets(expr, specfunc(f)); 
if numelems(res)<>0 then 
   print("Found f(x,t)"); 
else 
   print("could not find f(x,t)"); 
fi;
 

"Found f(x,t)"

4.13 How to find all functions in an expression?

Given expression \(3 \sin \left (x \right )+t +3 f \left (x , t\right ) t +g \left (x , t\right )\) find all functions, if any, in the expression.

Use indets with function

restart; 
expr := 3*sin(x)+t+3*f(x,t)*t+g(x,t); 
res  := indets(expr,function); 
if numelems(res)<>0 then 
   print("Found these functions",res); 
else 
   print("could not find any function)"); 
fi;
 

"Found these functions", f(x, t), g(x, t), sin(x)

4.14 find all functions except builtin math functions

Given expression \(3 \sin \left (x \right )+t +3 f \left (x , t\right ) t +g \left (x , t\right )\) find all functions, if any, in the expression but exclude the math functions such as \(\sin \) in the above.

restart; 
expr := 3*sin(x)+t+3*f(x,t)*t+g(x,t); 
res  := indets(expr, And( function, Not(typefunc(mathfunc)))); 
if numelems(res)<>0 then 
   print("Found these functions",res); 
else 
   print("could not find any function)"); 
fi;
 

"Found these functions", f(x, t), g(x, t)

4.15 How to obtain a list of all arguments of function?

use op

restart; 
op(1..,f(x,t)) 
 
    x, t
 

Note that op(0,f(x,t)) finds the function name.

4.16 Find functions whose first argument is \(z\)

restart; 
expr := 3*sin(z)+t+3*f(z,t,y)*t+g(x,t); 
res  := indets(expr, patfunc(identical(z), anything)); 
if numelems(res)<>0 then 
   print("Found these functions",res); 
else 
   print("could not find any function)"); 
fi;
 

gives

"Found these functions", f(z, t, y), sin(z)

4.17 Find functions whose second argument is \(t\)?

expr := 3*sin(z)+t+3*f(z,t,y)*t+g(x,t); 
res  := indets(expr, patfunc(anything, identical(t), anything)); 
if numelems(res)<>0 then 
   print("Found these functions",res); 
else 
   print("could not find any function)"); 
fi;
 

gives

"Found these functions", f(z, t, y), g(x, t)

4.18 How to use select with own type to find subexpressions?

Given expression such as \(3+(1+x)\sin x\) or \(3+(1+x)\sin ^2 x\) use select to find any  polynomial * sin^n  subexpressions.

restart; 
mytype_1 := ''`*`'( {polynom(And(algebraic, satisfies(u -> not has(u, I))),x), 
                     Or( 'specfunc(sin)'^integer, 'specfunc(sin)') 
                    } 
                  )'; 
select(type, 3+(1+x)*sin(x),mytype_1); 
select(type, 3+(1+x)*sin(x)^2,mytype_1);
 

Gives

                         (1 + x) sin(x) 
 
                                      2 
                        (1 + x) sin(x)
 

4.19 How to write structured types to match some expressions?

4.19.1 type for \(\sin ^m(x)\cos ^n(x)\)
restart; 
my_type:=''`*`'( { Or('specfunc'(sin),'specfunc'(sin)^Or(integer,rational)), 
                   Or('specfunc'(cos),'specfunc'(cos)^Or(integer,rational))})'; 
 
type(sin(x)^2*cos(x)^3,my_type); 
type(sin(x)^2*cos(x),my_type); 
type(sin(x)*cos(x),my_type); 
type(cos(x)*sin(x)^(1/2),my_type); 
 
 
           true 
           true 
           true 
           true
 

I could not find a way to avoid writing  Or('specfunc'(sin),'specfunc'(sin)^Or(integer,rational) in order to match both \(\sin x\) and \(\sin ^2 x\). For these things, I find Mathematica patterns more flexiable. The above can be done as follows in Mathematica

 
ClearAll[x,n,m,any] 
patt=any_.*Sin[_]^n_. * Cos[_]^m_. 
MatchQ[Sin[x]^2*Cos[2*x]^3,patt] 
MatchQ[Sin[x]^2*Cos[x],patt] 
MatchQ[Sin[x]*Cos[x],patt] 
MatchQ[Cos[x]*Sin[x],patt] 
 
      True 
      True 
      True 
      True
 

In Mathematica  n_.  says basically to match \(\sin x\) or \(\sin ^2 x\) since the dot says to match zero or more. So no need to duplicate things as I did above in Maple. There might be a way to do the same in Maple using structured type, but I could not find it. In General, I find patterns in Mathematica more flexible and easier to use for this sort of thing. Maple has patmatch command, but not as easy to use as Patterns in Mathematica.

4.20 select only indexed variables from an expression

use indets with type 'indexed'

expr:=16*a[3]+6*a[1]; 
terms:=indets(expr,'indexed'); 
 
         terms := {a[1], a[3]} 
 
#to find maximum index, then do 
 
map(x->op(x),terms) 
 
      {1, 3}
 

4.21 Given an expression, how to find all variables and functions in it?

Given say \(\frac {d^{2}}{d x^{2}}y \left (x \right )+n \left (\frac {d}{d x}y \left (x \right )\right )+3 = \sin \left (x \right )\) how to find all variables and functions in it, not including math functions such as \(\sin x\)?

So the result should be \(n,x,y(x)\).

ode:=diff(y(x),x$2)+n*diff(y(x),x)+3=sin(x); 
vars:=indets(ode, Or(  And(symbol,Not(constant)), And(function,Not(typefunc(mathfunc)) ) )) 
 
#gives 
#           vars := {n, x, diff(y(x), x), diff(y(x), x, x), y(x)}
 

I still need to work on excluding derivatives from the search.

4.22 How to check if an expression is integer, when it has symbols in it?

I had case where I needed to check if something is integer or not. The problem is that the result had a symbol \(n\) in it. I need a way to tell Maple that to check if the result can be an integer given that \(n\) is also an integer.

Using type does not work, since can’t use assumptions. One way is to use coulditbe as follows

restart; 
expr:=n-1+2*m; 
vars:=indets(expr,And(symbol,Not(constant))); 
coulditbe(expr,integer) assuming op(map(Z->Z::integer,vars)) 
 
#  true
 

In the above indets(expr,And(symbol,Not(constant))) picks all variables in the expression, and assuming op(map(Z->Z::integer,vars)) makes assumption that each is integer.

4.23 How to find parameters such as \(\pi \) in an expression?

Use

restart; 
expr:=4*Pi+sin(x); 
indets(expr,And(name,constant)) 
 
        {Pi}
 

4.24 How to find all derivatives \(y'(x)\) in an expression?

Given an expression such as

\[ \sin \left (x \right )+\left (\frac {d}{d x}y \left (x \right )\right )^{3}+\left (\frac {d}{d x}y \left (x \right )\right ) \ln \left (y \left (x \right ) \left (\frac {d}{d x}y \left (x \right )\right )^{2}\right )+\sqrt {\frac {d}{d x}y \left (x \right )}+\frac {x}{\left (\frac {d}{d x}y \left (x \right )\right )^{7}} \]

Find all \(y'(x)\) for any power that show up, so the result should be

\[ \left \{\frac {1}{\left (\frac {d}{d x}y \left (x \right )\right )^{7}}, \left (\frac {d}{d x}y \left (x \right )\right )^{2}, \left (\frac {d}{d x}y \left (x \right )\right )^{3}, \sqrt {\frac {d}{d x}y \left (x \right )}, \frac {d}{d x}y \left (x \right ) \right \} \]

Use indets with type identical(diff(y(x),x))^anything is used. But must use the flat option to work correctly.

restart; 
 
expr:= y(x)*diff(y(x),x)^(1/3)+sin(x)*diff(y(x),x)^3 + z*diff(y(x),x)*ln(y(x)*diff(y(x),x)^2) +diff(y(x),x)^(1/2) + x/diff(y(x),x)^7; 
t1:=identical(diff(y(x),x))^anything; 
t2:=identical(diff(y(x),x)); 
indets[flat](expr, 'Or'(  t1, t2 ));
 

gives

{diff(y(x), x)^(1/3), 1/diff(y(x), x)^7, diff(y(x), x)^2, diff(y(x), x)^3, diff(y(x), x), sqrt(diff(y(x), x))}
 

Without using flat it will given wrong result. For example

restart; 
 
expr:=diff(y(x),x)^2; 
t1:=identical(diff(y(x),x))^anything; 
t2:=identical(diff(y(x),x)); 
indets(expr, 'Or'(  t1, t2 ));
 

Gives

{diff(y(x), x)^2, diff(y(x), x)}
 

You see, it has extra diff(y(x), x) showing up. Adding flat it gives

restart; 
 
expr:=diff(y(x),x)^2; 
t1:=identical(diff(y(x),x))^anything; 
t2:=identical(diff(y(x),x)); 
indets[flat](expr, 'Or'(  t1, t2 ));
 

Now it gives

{diff(y(x), x)^2}
 

Which is the correct result.

4.25 How combine log terms?

To go from \(\ln (A B)\) to \(\ln A + \ln B\) need to use simplify with ln option but add assumptions that one of the terms is positive. Else it will not do it

restart; 
simplify(ln(A*B),ln); # no change 
simplify(ln(A*B),ln) assuming A>0;  # ln(A) + ln(B) 
simplify(ln(A*B),ln) assuming B>0;  # ln(A) + ln(B)
 

To go from \(\ln ( \frac {A}{B})\) to \(\ln A - \ln B\) need to use simplify with ln option but add assumptions that \(B>0\).

restart; 
simplify(ln(A/B),ln);  # no change 
simplify(ln(A/B),ln) assuming A>0;  # ln(A) + ln(1/B) 
simplify(ln(A/B),ln) assuming B>0;  # do this: -ln(B) + ln(A)
 

To go from \(\ln A + \ln B\) to \(\ln (A B)\) need to use combine with assumptions that either \(A\) or \(B\) is positive, else it will not do it.

restart; 
combine( ln(A) + ln(B),ln); # no change 
combine( ln(A) + ln(B),ln) assuming A>0; # ln(A*B) 
combine( ln(A) + ln(B),ln) assuming B>0  # ln(A*B)
 

To go from \(\ln A - \ln B\) to \(\ln \frac {A}{B} \) need to use combine with assumptions that either \(B\) is positive.

restart; 
combine( ln(A) - ln(B),ln);  #no change 
combine( ln(A) - ln(B),ln) assuming A>0;  # -ln(B/A) 
combine( ln(A) - ln(B),ln) assuming B>0   # use this  ln(A/B)
 

4.26 Find position in a list of items that are not numeric

Given list such as [1,2,3,4,5,x,y,8,9,Pi] find position of elements that are not numeric. In this case the answer should be [6,7,10]

restart; 
lis:=[1,2,3,4,5,x,y,8,9,Pi]; 
lis2:=select(x->not(type(x,numeric)),lis); 
map(x->ListTools:-Search(x,lis),lis2) 
 
    [6,7,10]
 

I could not find a way to do it using one command like with Mathematica. The first command above uses select to first find non numeric entries. The second command ListTools:-Search then find the index/position.

Maple’s ListTools:-Search should really have a version that allows one to select the element directly. Something like this

lis:=[1,2,3,4,5,x,y,8,9,Pi]; 
ListTools:-Search(x->not(type(x,'numeric')),lis,all)
 

4.27 How to change \(\arctan (y,x)\) to \(\arctan \left (\frac {y}{x}\right )\) in an expression

I needed to do this as I was translating Maple code to Sagemath. Where sagemath supports \(\arctan \) with only one argument.

Given an expression such as

\[ x +\arctan \left (y,x \right )+\sin \left (x \right ) \]

Convert it to

\[ x +\arctan \left (\frac {y}{x}\right )+\sin \left (x \right ) \]
evalindets(expr,'specfunc(arctan)',f->`if`(nops(f)=2,arctan(op(1,f)/op(2,f)),f))
 

4.28 How to find all symbols that represent variables in an expression?

Given an expression such as \(a+\sin (x) + \pi + y+ f(r) \) how to find all symbols in it, which will be \(a,x,y,r\)?

One way

expr:=a+sin(x) + Pi + y+ f(r); 
indets(expr,And(symbol,Not(constant)));
 

Another is

expr:=a+sin(x) + Pi + y+ f(r); 
indets(expr,assignable(name));
                                                                                    
                                                                                    
 

Both give {a, r, x, y}

4.29 How to change first argument of function?

This question came up in https://mathematica.stackexchange.com/questions/274535/replacing-only-variables-in-specific-locations-with-replace-all where the user wanted to I would like to replace R0 with r, but only in the arguments of functions.

The input they had is line = R0*f[R0,x] + R0^2*42*D[g[R0,x],x]

In Maple, this can be done as follows, which I think is a easier thanks to Maple’s strong type system.

line := R0*f(R0,x) + R0^2*42*diff(g(R0,x),x); 
evalindets(line, 'patfunc(identical(R0),anything)', Z-> subsop(1 = r, Z ));
 

Which gives

\[ \mathit {R0} f \left (r , x\right )+42 \mathit {R0}^{2} \left (\frac {\partial }{\partial x}g \left (r , x\right )\right ) \]

4.30 How to change last argument of function?

Given an expression which contains some different functions each with different number of arguments. Suppose we want to change only the last argument of each function if the last argument is \(x\), and change it to say \(x^2\).

how to do that?

Hence given R0*f(R0,x)+42*R0^2*D[2](g)(R0,x)+h(x,y,z,r,x) we want to change it to R0*f(R0,x^2)+42*R0^2*D[2](g)(R0,x^2)+h(x,y,z,r,x^2).

expr:= R0*f(R0,x) + R0^2*42*diff(g(R0,x),x)+ h(x,y,z,r,x); 
evalindets(expr, 'patfunc[reverse](anything,identical(x))', Z-> subsop(-1 = x^2, Z ));
 

Note the use of  subsop(-1 = x^2, Z ) where \(-1\) means the last entry in the argument of the function. This is basically same as last example, but uses patfunc[reverse] instead of just patfunc

4.31 How to remove last argument of function?

This is the same example as the above, but now we want to remove the last argument instead of changing it.

Hence, given an expression which contains some different functions each with different number of arguments. Suppose we want to remove only the last argument of each function if the last argument is \(x\).

how to do that?

Hence given R0*f(R0,x)+h(x,y,z,r,x) we want to change it to R0*f(R0)+h(x,y,z,r).

expr:=R0*f(R0,x)+h(x,y,z,r,x) 
evalindets(expr, 'patfunc[reverse](anything,identical(x))', Z-> subsop(-1 = NULL, Z ));
 

Be careful using the above on expression that has diff(f(y,x),x) as this will give 0, because we basically removed the variable of the differentiation.

4.32 How to find a pattern inside an expression

Given \(3 \,{\mathrm e}^{x}+\sin \left (a \,{\mathrm e}^{x}\right ) f\left ({\mathrm e}^{5 x}\right )\) how to find all terms with pattern anything*exp ? If we do this

expr:=3*exp(x)+sin(a*exp(x))*f(exp(5*x)); 
indets(expr,`&*`(anything,'specfunc(exp)')); 
 
#        {a*exp(x), 3*exp(x)}
 

We see it did not find exp(5*x) this is because there is nothing multiplying the exp function. To find this we add Or like this to count for both cases

expr:=3*exp(x)+sin(a*exp(x))*f(exp(5*x)); 
indets[flat](expr,Or( `&*`(anything,'specfunc(exp)'), 'specfunc(exp)' )) 
 
 
#        {a*exp(x), 3*exp(x), exp(5*x)}
 

The flat option is needed, as without it this will be the result

expr:=3*exp(x)+sin(a*exp(x))*f(exp(5*x)); 
indets(expr,Or( `&*`(anything,'specfunc(exp)'), 'specfunc(exp)' )) 
 
#       {a*exp(x), 3*exp(x), exp(x), exp(5*x)}
 

4.33 How to find parts of a Sum?

Given an inert Sum such as

\[ r = \sum _{n=2}^{\infty } a_{n -1} x^{n -1} \]

How to obtain the body of the sum, the index variable, the lower starting value and the upper limit?

r:=Sum(a[n - 1]*x^(n - 1), n = 2 .. infinity); 
op(0,r)  #head 
                              Sum 
op(1,r) #body 
                       a[n - 1] x^(n - 1) 
 
op(2,r) # sum specs 
                       n = 2 .. infinity 
 
lhs(op(2,r))  #name of summation index 
                               n 
 
rhs(op(2,r))  # lower..upper limits 
                         2 .. infinity 
 
op(1,rhs(op(2,r)))  #lower limit 
                               2 
 
op(2,rhs(op(2,r)))  #upper limit 
 
                    infinity
 

4.34 find if sequence or list is inside another and the indecies

Given a 1D container, such as vector or list, called \(A\), how to find if this sequence is inside another sequence say \(B\) and the indecies in \(B\) where the sequence \(A\) is located?

Use ArrayTool in version 2023

A:=[1,3,5]; B:=[1,3,4,5]; 
 
status,indices_list := ArrayTools:-IsSubsequence( A, B ,'output' = ['check','indices'],'match'='exact'); 
if status then 
   print("Sequence ",A," Was found in ",B," At indices ",indices_list); 
else 
   print("Sequence ",A," Was not found in ",B); 
fi;
 

The above gives

 "Sequence ", [1, 3, 5], " Was found in ", [1, 3, 4, 5], " At indices ", [1, 2, 4]
 

If \(A\) was not sequence inside \(B\), then status will be false otherwise.

4.35 find if some type inside some expression and its location

Use membertype

restart; 
expr:=cos(x)+x+9+sin(x)*(x^2+4); 
membertype( polynom(anything,x), expr,'loc' ); 
       true 
loc; 
       2
 

The above says there is a polynomial in \(x\) inside the expression at op(2,expr) notice that \(x^2+4\) is not a polynomial since the expression will expand and \(\sin x\) will be multiplied by it causing it not to become polynomial. So only \(9+x\) is the polynomial. The location is where the memeber starts at. Notice that Maple sorts polynomial from lower to higher powers.

restart; 
expr:=cos(x)+x+9+sin(x)*(x^2+4); 
membertype( integer, expr,'loc' ); 
       true 
loc; 
       3
 

The above says that there is an integer (which is \(9\) in this example) inside the expression at op(3,expr)

4.36 How to replace generic function inside derivative?

I had case where I wanted to substitute  _F=(y-x^2)/x in an expression obtained which is  x*diff(F1, x) + 2*y*diff(F1, y)

Using eval does not work

restart; 
eval(x*diff(F1, x) + 2*y*diff(F1, y),F1=(y-x^2)/x); 
  0
 

Also using delayed does not work

restart; 
eval('x*diff(F1, x) + 2*y*diff(F1, y)',F1=(y-x^2)/x); 
value(%) 
  0
 

ALso using subs does not work

restart; 
subs(F1=(y-x^2)/x,x*diff(F1, x) + 2*y*diff(F1, y)) 
  0
 

However, delayed with subs finally worked

restart; 
subs(F1=(y-x^2)/x,'x*diff(F1, x) + 2*y*diff(F1, y)'); 
value(%) 
 
x*(-2 - (-x^2 + y)/x^2) + 2*y/x
 

So the rule is, if you want to replace a function inside diff, use subs and not eval, and make sure to delay evaluation of the expression and then use value() to obtain the final result.

4.37 Examples how to match types

These are examples how to match expression types

  1. expr is product a*b which is matched using

    type(a*b,`&*`(anything,anything)) 
                 true
                                                                                        
                                                                                        
          
     
    

    The above can also be written using infix notation

    type(a*b,  anything &* anything) 
                 true
     
    

    However, the above only match product of two terms. To match 3*a*b use

    type(3*a*b,`*`) 
                 true
     
    
  2. expr is division a/b which is matched using same as `*`

    type(a/b,`&*`(anything,anything)) 
                 true
     
    
  3. Match type of a*f(x), which is anything times a function that takes one argument \(x\).

    type(a*f(x),`&*`(anything,patfunc(identical(x),anything))) 
                 true
     
    

    Using patfunc is better than using function

    type(a*f(x,y),`&*`(anything,function(identical(x)))) 
                 true
     
    

    Because patfunc matches on \(f(x,y,z,\dots )\) and not just function which takes only one argument \(f(x)\). But if you know your function takes only one argument, then use function

  4. To match 3*y/x. This was tricky. Had to use

    expr:=3*y/x; 
    type(expr, `&*`(anything,identical(y),`^`(identical(x),-1))) 
             or 
    type(expr, `&*`(identical(y),`^`(identical(x),-1))) 
     
                 true
     
    

    I used or to account for possible expr:=y/x, i.e. missing constant at front. Note that

    expr:=3*y/x; 
    type(3*y/x, `&*`(anything,identical(y/x))) 
                false
     
    

    Does not match, since 3*y/x is actually 3*y times 1/x internally.

  5. Match on f(b* y/x)

    type(f(3*y/x),function(`&*`(anything,identical(y),`^`(identical(x),-1)))) 
     
                true
     
    
  6. Match on f(b* y/x) or f(y/x)

    expr:=f(3*y/x); 
    type(expr, function(`&*`(anything,identical(y),`^`(identical(x),-1)))) 
       or 
    type(expr, function(`&*`(identical(y),`^`(identical(x),-1)))) 
     
                true
     
    

    Again, had to use or to account for missing constant multipler.

  7. Match on a*f(b* y/x)

    expr:=a*f(3*y/x); 
    type(expr, `&*`(anything,patfunc(`&*`(anything,identical(y),`^`(identical(x),-1))))) 
      true
     
    
  8. Match against 9+3 y/x

    expr:=9+3*y/x; 
    selector:=`&+`(anything,`&*`(anything,identical(y),`^`(identical(x),-1))): 
    type(expr, selector); 
     
                 true 
     
    select(type,[expr],selector); 
         [9 + 3*y/x]
     
    

    Notice in the above, when using select we need to put the expression inside a list, as select looks at each operand, This way the whole expression is taken as one. If we just used select(type,expr,selector); it would not have found it.

    To use patmatch the command becomes

    patmatch(expr, a::anything+b::anything*y/x,'la'); 
    la 
     
        [a = 9, b = 3]
     
    

    The nice thing about patmatch is that it allowed one to assign variable to parts of the expression automatically.

  9. Match against 9+f(3 y/x) where now \(f\) is function. Using patmatch. I could not do this in one command, as all my attempts failed:

    expr:=3+4*x*f(3*y/x); 
    body_of_function:=C::anything*y/x; 
    patmatch(expr,A::anything+B::anything*F::function(C::anything*y/x),'la'); 
    patmatch(expr,A::anything+B::anything*F::patfunc(C::anything*y/x),'la'); 
     
    Error, (in PatternMatching:-AlgStruct:-Match) testing against an invalid type 
    Error, (in type/patfunc) testing against an invalid type
                                                                                        
                                                                                        
          
     
    

    So I had to do it in two steps. First match on the function as whole, then use that to match on f(3*y/x) in second stage, like this

    expr:=3+4*x*f(3*y/x); 
    patmatch(expr,A::anything+B::anything*F::function(anything),'la'); 
    la; 
     
    [A = 3, B = 4*x, F = f(3*y/x)]
     
    

    And now

    assign(la); 
    A:='A'; 
    patmatch (op(1,F),A::anything*y/x,'la'); 
    la 
     
    [A = 3]
     
    

Overall, I find Mathematica’s pattern matching constructs much simpler and more intutive to use and easier to learn as there are many examples and tutorials. For example, the last example above in Mathematica could be done as follows

expr=9+(4*x)*f[3*y/x]; 
Cases[{expr},any0_.+ any1_.*any2_[any3_.*y/x]:>{any0,any1,any2,any3}] 
 
{{9, 4 x, f, 3}}
 

Maple’s help pages are not good at all and provide little or no examples to learn from compared to Mathematica’s excellent help pages. For any serious pattern matching tasks, I would use Mathematica. Maple has a better debugger and hence easier to debug the code because of this. So it is a tradeff between these two systems.

4.38 On the order of terms when using indents

I was trying to match on anyfunction that has \(x\) inside its arguments. It turned out that matching \(f(a x)\) vs. \(f(a+x)\) needed to have the identical(x) being placed first when it is a sum and last when it is a product. Very strange. Just be aware of this

indets(f(a+x),function(`&+`(anything,identical(x)))); 
#failed 
    {}
 

But

indets(f(a+x),function(`&+`(identical(x),anything))); 
 
   {f(x + a)}
 

While with product, it is the other way around

indets(f(a*x),function(`&*`(anything,identical(x)))); 
 
    {f(a*x)}
 

But now this fail

indets(f(a*x),function(`&*`(identical(x),anything))); 
#fail 
    {}
 

I have not yet figure how to tell it that the order does not matter. Maple 2023.1

A better way than the above, if I want to find any function that takes in \(x\) or \(y\) as arguments is to use patfunc like this

indets(f(a*x+b+y),patfunc(anything,`Or`({identical(x),identical(y)}))); 
     {f(a*b + y)} 
 
indets(f(b+y),patfunc(anything,`Or`({identical(x),identical(y)}))); 
     {f(b + y)} 
 
indets(exp(a*x),patfunc(anything,`Or`({identical(x),identical(y)}))); 
      {exp(a*x)} 
 
indets(exp(a+x),patfunc(anything,`Or`({identical(x),identical(y)}))); 
{exp(x + a)}