See http://www.maplesoft.com/applications/view.aspx?SID=1533&view=html&L=G
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]
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.
Given
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 \} \)
I wanted to simplify an expression which could have csgn() in it, and find all the arguments.
One way is
restart; expr:=(1+csgn(a)*a)/(3*csgn(b)*b): expr:=subsindets(expr,'specfunc( anything, csgn )',f->1);
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.
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));
expr:=subsindets(expr,'specfunc( anything, abs )',f->op(f));
For an example, How to find list of all \(\ln \) functions in this expression?
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))}
Given
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))
Given
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);
Given
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);
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)"
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)
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)
Given function such as \(f(x,t)\), how to find all its arguments \(x,t\)? use op
restart; op(1..,f(x,t)) x, t
Note that op(0,f(x,t)) finds the function name.
Given an expression, we want to find list of all the arguments of such function, say \(y(.)\) in that expression. This can be used for example to check if the arguments of such a function are valid during parsing.
One way is to use indets to select all such functions from the expression, then use op as above to
find the arguments. Here is an example
expr:=y(3)+y(x)+7+y(Pi)+y([a+b])+h(z)+exp(x); L:=indets(expr,'specfunc'(anything,y)); map(X->op(1,X),L); {3, Pi, x, [a + b]}
Given an expression used for initial/boundary conditions, such as D(y)(3)+(D@@2)(y)(0)=1, the
question is, how to obtain all arguments of each D in the above to verify that it does not include
the independent variable \(x\) in this example?
One way is to use indets to select all such functions from the expression, then use op as above to
find the arguments.
expr:=D(y)(3)+(D@@2)(y)(0)+1/(D@@3)(y)(x)=0; (lhs-rhs)(expr); L:=indets(%,':-De'); map(X->op(1,X),L); if has(%,x) then error "Can not have x in argument for D used for initial/boundary conditions"; fi;
Which gives
Error, Can not have x in argument for D used for initial/boundary conditions
because we had (D@@3)(y)(x) there.
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)
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)
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)
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 flexible. 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.
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}
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.
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.
Use
restart; expr:=4*Pi+sin(x); indets(expr,And(name,constant)) {Pi}
Given an expression such as
Find all \(y'(x)\) for any power that show up, so the result should be
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.
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)
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)
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
Convert it to
evalindets(expr,'specfunc(arctan)',f->`if`(nops(f)=2,arctan(op(1,f)/op(2,f)),f))
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}
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
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
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.
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)}
Given an inert Sum such as
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
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 indices 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.
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 member 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)
Given a list, we need to check that all entries are same type, say `=`. But the type can be
anything.
One way is to use andmap with the type function. Here is an example
restart; L:=[3+x=0, 2+y(x)-3=0, 5=0, 7*x=2]; #check all entries are of type `=` andmap(X->type(X,`=`),L); #true L:=[3+x=0, 2+y(x)-3=0, 5]; andmap(X->type(X,`=`),L); #false
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.
These are examples how to match expression types
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
expr is division a/b which is matched using same as `*`
type(a/b,`&*`(anything,anything)) true
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
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.
Match on f(b* y/x)
type(f(3*y/x),function(`&*`(anything,identical(y),`^`(identical(x),-1)))) true
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 multiplier.
Match on a*f(b* y/x)
expr:=a*f(3*y/x); type(expr, `&*`(anything,patfunc(`&*`(anything,identical(y),`^`(identical(x),-1))))) true
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.
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 intuitive 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 trade between these two systems.
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)}