I am trying to set up rules as follows:


If the arguments are the same the output is zero:


If any of the arguments have Head Plus then distribute the function over the Plus:


or CircleTimes[x_Plus,y_]:=Distribute[CircleTimes[x,y],Plus];

If any of the arguments have Head Times then pull out the scalar coefficient:


If an argument switch is needed to apply the rules above then the sign should be reversed:


And following are the other terminating conditions:


What is the best and minimal way to implement this?


1 Answer 1


I think that there is some ambiguity in your description, so this probably needs some tweaking, but here goes...

CircleTimes[x_Plus,y_]:=Distribute[Unevaluated[CircleTimes[x,y]]];(* The Unevaluated avoids infinite recursion. *)
CircleTimes[Times[a_?NumberQ,xs__],Times[b_?NumberQ,ys__]]:=a b CircleTimes[Times[xs],Times[ys]]; (* I'm assuming this is what you want *)
CircleTimes[Times[a_?NumberQ,xs__],y_]:=a CircleTimes[Times[xs],y];
CircleTimes[x_,Times[b_?NumberQ,ys__]]:=b CircleTimes[x,Times[ys]];

As for your terminal conditions, they seem fine, but incomplete.

I don't know what constraints you might be applying to your inputs, so this could probably be simplified if those were clarified. For example, in the definition involving Times I assumed that you would only know which element should be considered the scalar if there were a numeric element. The standard sorting would, I believe, bring numbers to the front, so that's why the definition works. If what you really mean is any factor that's not one of the hatted symbols, then that should be made explicit.

Also, it wasn't clear why/when the negation rule should apply, since you said "if any of the arguments have Head ...". But maybe that actually applied to the terminal conditions, and that's why they're incomplete? As long as there's no possibility of infinite recursion, your reversal/negation rule is fine as long as it's the most generic rule (so it'll be applied only if nothing else matches).

If this doesn't produce what you expected, then it would be helpful if you provided a set of test cases showing inputs with expected outputs.

  • $\begingroup$ Thank you my issue was the CircleTimes[x,y] blowing up inside the Distribute causing infinite recursion. Also CircleTimes[x_,y_]:=-CircleTimes[y,x] removes the need for both CircleTimes[x_Plus,y_] and CircleTimes[x_,y_Plus] definitions to be defined and same for the Times case. Everything works fine now! $\endgroup$
    – user13892
    May 16, 2022 at 0:38
  • $\begingroup$ My other question was if there was a need for both cases CircleTimes[x_Plus,y_] and CircleTimes[x_,y_Plus] to be present, is there a better way then CircleTimes[x_,y_]/;MemberQ[{Head@x,Head@y},Plus] to combine them. $\endgroup$
    – user13892
    May 16, 2022 at 0:40
  • $\begingroup$ I think that’s a matter of style $\endgroup$
    – lericr
    May 16, 2022 at 0:51

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.