# Programmatic creation of rules

Suppose I am given two positions, as well as b[0, 0] and b[0, 1]/Sqrt[2] + b[1, 1]/Sqrt[2], where b is some undefined symbol, so that the expressions remain in an unevaluated form. I would like to create the following rule: whenever the argument of b in position 1 is 0 and the argument in position 2 is 0, replace this using the latter expression. For example, let's say the positions are just the first and second arguments, and I have several expressions of the form b[x,y,z]. Looking at what I am given, I can manually write down the rule like below.

rule=b[0, 0, x_] -> b[0, 1, x]/Sqrt[2] + b[1, 1, x]/Sqrt[2]


Then I would have

b[0,0,0]/. rule
(*b[0, 1, 0]/Sqrt[2] + b[1, 1, 0]/Sqrt[2]*)


and

b[0,0,1]/.rule
(*b[0, 1, 1]/Sqrt[2] + b[1, 1, 1]/Sqrt[2]*)


Here's my attempt at creating the rule programmatically (I haven't gotten around to making this work for given positions yet, so assuming first and second argument).

rule=b[0, 0] -> b[0, 1]/Sqrt[2] + b[1, 1]/Sqrt[2] /.
b[x_, y_] -> b[x, y, Blank[]]


But this doesn't give me what I want, because the Blank[] is not named and I don't know how to make it named since it is in the r.h.s. of the rule.

b[0,0,0]/. rule
(*b[0, 1, _]/Sqrt[2] + b[1, 1, _]/Sqrt[2]*)


Can anyone help?

If I understand correctly, what you need is to replace all of the occurrences of b[x, y] in a rule with b[x, y, z_] where x and y are constants and z is a pattern object to be matched. To start with, you need to use RuleDelayed (written as :>), then you use z_ on the right hand side, like this:

(b[0, 0] -> b[0, 1]/Sqrt[2] + b[1, 1]/Sqrt[2]) /. b[x_, y_] :> b[x, y, z_]
(*b[0, 0, z_] -> b[0, 1, z_]/Sqrt[2] + b[1, 1, z_]/Sqrt[2]*)


Though the output is still not quite right, as the output rule has z_ on the right hand side. So to fix this you need to match the pattern of the Rule, then modify the left and right separately, like this:

rule = (
b[0, 0] -> b[0, 1]/Sqrt[2] + b[1, 1]/Sqrt[2]
) /. {
Rule[left_, right_] :> RuleDelayed[
Append[left, z_],
Evaluate[right /. {b[x_, y_] :> b[x, y, z]}]
]
} /. z$->z (*b[0, 0, z_] :> b[0, 1, z]/Sqrt[2] + b[1, 1, z]/Sqrt[2]*)  To go through the elements: • The parenthesis at the start contain the rule you are modifying • Rule[left_, right_] matches to your rule • RuleDelayed makes a new rule (for the output) • Append[left, z_] adds the new pattern object z to the left hand side of the rule (using a ReplaceAll here does not substitute in the constants properly) • The Evaluate on the right hand side of the output replacement is because we are trying to output a RuleDelayed, meaning the right hand side will be left unevaluated by default. • /. z$->z at the end fixes an automatic substitution of z$ into your rule (to do with automatic scoping) And to test: b[0, 0, 1] /. rule (*b[0, 1, 1]/Sqrt[2] + b[1, 1, 1]/Sqrt[2]*)  Note that you will need to make sure you clear z before you use this rule otherwise its value will be substituted in. It's not the neatest solution but it should reliably do what you need. • +1, to avoid relying on z$ renaming you could go with something like Module[{h}, h[Append[left, z_], right /. {b[x_, y_] :> b[x, y, z]}] /. h -> RuleDelayed] – Kuba Nov 15 '16 at 12:47

Here's my swing at trying to solve this. First define this function:

ruleTransform[yourRule_] :=
MapAt[
Append[#, x_] &,
yourRule,
1
] /. b[a1_, a2_] :> b[a1, a2, x]


Next, you throw in the rule you want to change:

ruleTransform[b[0, 0] -> b[0, 1]/Sqrt[2] + b[1, 1]/Sqrt[2]]


This should give you the rule you needed.