1
$\begingroup$

I would like to match things like

Times[Cycles[_],Cycles[_],..]

and replace them with

PermutationProduct[Cycles[_],Cycles[_],..]

For example, Times[Cycles[{{1,2}}],Cycles[{}]] should become PermutationProduct[Cycles[{{1,2}}],Cycles[{}]].

On the other hand, Times[2,Cycles[{}]] should not match.

To be specific: I want to match an expression if and only if its head is Times and the arguments to the head all have head Cycles. In this case, I want to replace the head with PermutationProduct.

I attempted to use the rule Times[b:{Cycles[_]..}] -> PermutationProduct[b] but this did not work -- somehow b matches the entire expression, including the Times, and the rule does absolutely nothing! Any pointers would be greatly appreciated. Happy to add some context about what I'm actually doing if that would help, but I think this ought to be a straightforward case of me not understanding how patterns work.

$\endgroup$
2

2 Answers 2

2
$\begingroup$

You have hit a common issue when using Times as a pattern. Observe the following:

Times[b:{Cycles[_]..}]
(* b : {Cycles[_] ..} *)

See what happened? Times disappeared! Why? Well, it's the feature of autosimplification in Mathematica. Times[x] is evaluated to x (which makes sense if you think about it). To prevent this, you have to use, for example, HoldPattern. Moreover, use RuleDelayed instead of Rule, and don't wrap Cycles in a list, because Times does not contain a list but separate arguments.

expr = Times[Cycles[{{1, 2}}], Cycles[{}]];
expr /. HoldPattern[Times[b : _Cycles ..]] :> PermutationProduct[b]
(* Cycles[{{1, 2}}] *)

This will in fact also match Times[2, Cycles[{}]], but it shouldn't be a problem since PermutationProduct will give back the same result. If you really want to avoid this, you can specify that there needs to be at least two Cycles present:

HoldPattern[Times[b : Repeated[_Cycles, {2, Infinity}]]] :> PermutationProduct[b]
$\endgroup$
1
  • $\begingroup$ Ah, this makes sense! Thanks so much $\endgroup$ Commented Apr 30 at 6:34
1
$\begingroup$

How about using an If ?

e = Times[Cycles[{{1, 2}}], Cycles[{{4, 5}}]]

If[(Head[e] === Times) && AllTrue[  e, Head[#] === Cycles &], 
 PermutationProduct @@ e, e]

You can try it and see if this works. I have not used PermutationProduct. If this does not work, will delete this.

$\endgroup$

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