3

I want to define a function to check whether the expression is the sum of these terms

a*x+b*y^n+c*Exp[k*z]
(* n can be 1*)

These a,b,c can be 0 but not all 0. And Exp[k*z] should include the case Power[e,k*z].

I found

a_.*x+b_.*y^(n_.)+c_.*Exp[k_.*z]

didn't work.

(For test {b y^-3 + c E^(k z)} /. a_.*x + b_.*y^(n_.) + c_.*Exp[k_.*z] -> f[q])

How should I define the pattern?

Curious Cat
  • 193
  • 8
  • Do you want to say: a,b cannot both be zero and c can never be zero? It is also a good idea to include some test patterns. And what is f[q]? Thanks. – Syed Oct 22 '22 at 16:25
  • I mean the sum is not a 0. f[q] is just used for test. It could be anything. I am looking for a pattern that is the sum of these terms except for 0 which is 0*x+0*y^n+0*Exp[k*z]. – Curious Cat Oct 22 '22 at 16:31
  • " And Exp[k*z] should include the case Power[e,k*z]" which means c cannot be zero? – Syed Oct 22 '22 at 16:33
  • No. c can be 0. a*x+b*y^n is also the matched expression. Exp[k*z] is mathematically identical to Power[e,k*z]. However, they have different Heads so the Mathematica cannot identify both at the same time using one pattern. – Curious Cat Oct 22 '22 at 16:37

2 Answers2

4

A similar question was asked on this stack exchange page about an equivalent for nothing for patterns. The solution was to use Optional. Using one of the answers there one can define a function to check whether the expression has the right form using MatchQ :

Note : I do not consider the case where the pattern is a subexpression of a larger expression. I am assuming you do not consider the case where the expression contains more terms than those of the requested pattern. For example, I consider that r+x+2y^2 does not fit the right condition as it contains an addition with r although (x+2y^2) fits the criteria. Is that the condition that you wanted ?

sumcheck = MatchQ[#, (lin : _. x : 0) + (ypow : _. y^_. : 
  0) + (exp : _. Exp[_.*z] : 0)] &

Test :

{#, sumcheck[#]} & /@ {a*x + b*y^n + c*Exp[k*z], b*y^n + c*Exp[k*z], 
0, c*Exp[k*z], y, 4, b*y^n + c*Exp[k*l], 
m + a*x + b*y^n + c*Exp[k*z], k + a*x}

Out: $\left( \begin{array}{cc} a x+b y^n+c e^{k z} & \text{True} \\ b y^n+c e^{k z} & \text{True} \\ 0 & \text{False} \\ c e^{k z} & \text{True} \\ y & \text{True} \\ 4 & \text{False} \\ b y^n+c e^{k l} & \text{False} \\ a x+b y^n+c e^{k z}+m & \text{False} \\ a x+k & \text{False} \\ \end{array} \right)$

userrandrand
  • 5,847
  • 6
  • 33
  • By the way, .+x means x plus something or x plus 0 and _.x means x times something or x times 1. The pattern _.x does not include the case 0*x because _. uses the default option for the operator considered which is the neutral element for the operator. Therefore, _. uses 0 for addition and 1 for multiplication. That can be checked using DefaultValues[Plus] and DefaultValues[Times]. For more information on `.one may check the documentation forDefaultandOneIdentity`. – userrandrand Oct 23 '22 at 14:32
  • Wonderful! How neat! For the r, I can use FreeQ to wipe it up. – Curious Cat Oct 23 '22 at 15:07
  • @CuriousCat What do you mean you can use FreeQ for the case where there is an r ? – userrandrand Oct 23 '22 at 16:34
  • Should the pattern match r+x+2y^2 ? The code I gave does not match that case. – userrandrand Oct 23 '22 at 16:35
  • Yes, r+... should be matched if r is a constant to x,y,z. I meant, r is treated as a constant to x, y, z. So I can use Select together with FreeQ to extract those terms containing x,y,z. If the extracted term is not the sum of the form then it should be False. – Curious Cat Oct 23 '22 at 19:06
  • So did you also want it to match just r or just a number like 5 ? You said it should not evaluate to 0 but given that you allow constant terms you might also consider the number 2 as something that could match – userrandrand Oct 23 '22 at 23:08
  • If you allow constant terms independent of x,y or z then you could check for the case where the term is 0 and treat that case a part and then use something like Clear[sumcheck]; sumcheck[sum_] := MatchQ[sum, (const : (_?(FreeQ[#, x | y | z] &)) : 0) + (lin : _. x : 0) + (ypow : _. y^_. : 0) + (exp : _. Exp[_.*z] : 0)] but that will also match 0 which is why you have to consider the case where it is zero apart. – userrandrand Oct 23 '22 at 23:11
  • If you do not want to consider the case where nothing depends on x, y or z, that is, the case where you only have symbolic or numeric constants, then if you do not want to consider that case, maybe you can use Clear[sumcheck]; sumcheck[sum_] := MatchQ[sum, (const : (_?(FreeQ[#, x | y | z] &)) : 0) + _?(MatchQ[#, (lin : _. x : 0) + (ypow : _. y^_. : 0) + (exp : _. Exp[_.*z] : 0)] &)] – userrandrand Oct 23 '22 at 23:21
  • Yeah. I made it like sumcheck = If[FreeQ[#, x | y | z], False, MatchQ[ExpandAll[ Select[#, (\[Not] FreeQ[#, x | y | z] &)]], (lin : _. x : 0) + (ypow : _. y^_. : 0) + (exp : _. Exp[_.*z] : 0)]] &; What I want is that a constant shift to the sum is ok but I am not interested in the case of nothing 0. – Curious Cat Oct 23 '22 at 23:28
  • you did not specify whether you sumcheck to evaluate just r or 5 to True – userrandrand Oct 23 '22 at 23:30
  • like sumcheck[2] – userrandrand Oct 23 '22 at 23:30
  • 1
    Yes. If there is only a constant, I don't treat it as the sum of a x+b y^n+c E^(k z). – Curious Cat Oct 23 '22 at 23:32
3

This feels a bit jenky, but maybe it'll work. I'm making a couple of assumptions, so you'll probably need to refine. Here is a list of cases that attempt to match individual terms:

{HoldPattern[Times[_, Power[E, Times[___, z, ___]]]],
 HoldPattern[Power[E, Times[___, z, ___]]],
 Power[E, z],
 HoldPattern[Times[___, Power[y, _], ___]],
 HoldPattern[Times[___, y, ___]],
 HoldPattern[Times[___, x, ___]],
 y,
 x}

You can turn this into a single pattern with Alternatives.

Your test didn't make much sense to me, since you seem to want to match the whole expression at once, so instead I defined a helper predicate:

IsMatch[expr_Plus] :=
  AllTrue[List @@ expr, IsMatch];
IsMatch[expr_] := With[
  {cases =
    {HoldPattern[Times[_, Power[E, Times[___, z, ___]]]],
     HoldPattern[Power[E, Times[___, z, ___]]],
     Power[E, z],
     HoldPattern[Times[___, Power[y, _], ___]],
     HoldPattern[Times[___, y, ___]],
     HoldPattern[Times[___, x, ___]],
     y,
     x}},
  MatchQ[expr, Alternatives @@ cases]]

Some tests:

testCases =
  {b y^-3 + c E^(k z),
   a*x + b*y^n + c*Exp[k*z],
   a*x + b*y^n,
   a*x + b*y^n + c*Exp[k*z],
   a*x + b*y^1 + c*Exp[k*z],
   x + b*y + Exp[k*z],
   a x,
   b y,
   Exp[z]}; 
IsMatch /@ testCases
(* {True, True, True, True, True, True, True, True, True} *)
lericr
  • 27,668
  • 1
  • 18
  • 64
  • Thanks. There is a case that E^(Log[Exp[k*z]]) is also Exp[k*z] and thus there are infinite possiblities. So we cannot list all the possible cases. I want to use ===. But I don't know how to use it for a pattern. – Curious Cat Oct 22 '22 at 17:51
  • These patterns already cover an infinite number of possibilities. We should be able to list all of the possibilities. If you can't enumerate those possibilities, then the problem is unsolvable. You must think that it actually is solvable, or you wouldn't have asked. Here's my suggestion, and let's assume that you stick with something like the IsMatch predicate... – lericr Oct 22 '22 at 18:16
  • Start writing out test cases. Specific expressions that "pass" the as-yet-to-be-implemented predicate. After you get a few, try your hand at implementing the predicate. Then try a few more until you find one that fails your predicate. Update your predicate. Repeat until you have reached a sufficient level of confidence. You might also need to test for non-matching expressions, but I don't know your context so I don't know if that's relevant. – lericr Oct 22 '22 at 18:16
  • As for using ===, I suspect that that won't work. SameQ expects exact matching of the two expressions structurally. – lericr Oct 22 '22 at 18:18
  • Thanks. I will try it out. – Curious Cat Oct 22 '22 at 18:56