# Symbolic manipulation of expression with undefined function

I have an expression which is a sum of undefined function v[n1,n2,n3,n4] with 4 arguments (n_i are integers):

expr=a*v[n1, n2, n3, n4] + b*v[n5, n6, n7, n8] + c*v[n9, n10, n11, n12] + ....


Now I increase or decrease the i-th argument of v in expr, and also multiply each term with the value of v[[i]].

For example:

example=v[1,1,1,1]+10*v[0,0,2,0]
inc[example,3] (* first argument is the expression, second argument is the index of v that should be increased *)
(*
example -> example=v[]*v[1,1,1+1,1]+10*v[]*v[0,0,2+1,0]
-> example=1*v[1,1,2,1]+10*2*v[0,0,3,0]
*)


In reality, my v has much more terms, therefore hardcoding inc for each index is not feasible. I think I know how to do it with an ugly For loop, but I hope that there is some clever Mathematica-style way.

example = v[1, 1, 1, 1] + 10*v[0, 0, 2, 0];


Using a replacement rule:

inc[ex_, p_] :=
ex /. v[a_, b_, c_, d_] ->
{a, b, c, d}[[p]] (v @@ ({a, b, c, d} +  UnitVector[4, p]))


and for a more general case - i.e., for an arbitrary number of arguments of v (thanks: kgrl):

inc[ex_, p_] := ex /. v[a__] :> {a}[[p]] (v @@ ( {a} + UnitVector[Length@{a}, p] ))


Then

inc[example, 3]


20 v[0, 0, 3, 0] + v[1, 1, 2, 1]

and

inc[example, 2]


v[1, 2, 1, 1]

• wow that is very beautiful. i was trying replacement rules for some time, but didnt know how to access one particular element of v[..]. It is very clever how you get a specific argument by producing a list and selecting it via [[p]] - Thanks a lot! – Mario Krenn Dec 28 '16 at 18:49
• Glad you like it! – corey979 Dec 28 '16 at 18:51
• Array[KroneckerDelta, {4, 4}] is just IdentityMatrix, no? And, since you're just extracting the p-th row, then what you actually want is UnitVector[4, p]... – J. M.'s torpor Dec 28 '16 at 18:59
• @J.M. Ha! I had a feeling something is way too complicated here. Thanks. – corey979 Dec 28 '16 at 19:06
• (+1) perhaps slightly simpler and more general: ex /. v[a__] :> {a}[[p]] (v @@ ({a} + UnitVector[Length[{a}], p])) – kglr Dec 28 '16 at 21:03

Update: a simpler version for OP's specific case:

ClearAll[f2]
f2[exp_, p_] := exp /. v[x__] :> v[x][[p]] MapAt[1 + # &, v[x], {p}]

exp = 10 v[0, 0, 2, 0] + v[1, 1, 1, 1] + k v[1, 2, 3, 4];
f2[exp , 2]


v[1, 2, 1, 1] + 2 k v[1, 3, 3, 4]

f2[exp, 3]


20 v[0, 0, 3, 0] + v[1, 1, 2, 1] + 3 k v[1, 2, 4, 4]

Original post:

ClearAll[foo]
foo = # /. a : #2[__] :> a[[#4]] MapAt[#3, a, {#4}] &;
(* or foo[exp_, func_, tr_, p_]:= exp/. a: func[__] :> a[[p]] MapAt[tr, a, {p}] *)


Examples:

example = v[1, 1, 1, 1] + 10*v[0, 0, 2, 0] + 5 w[1, 2, 3];

foo[example, v, 1 + # &, 2]


v[1, 2, 1, 1] + 5 w[1, 2, 3]

foo[example, v, 1 + # &, 3]


20 v[0, 0, 3, 0] + v[1, 1, 2, 1] + 5 w[1, 2, 3]

foo[example, v, h, 3]


20 v[0, 0, h, 0] + v[1, 1, h, 1] + 5 w[1, 2, 3]

foo[example, w, h, 3]


10 v[0, 0, 2, 0] + v[1, 1, 1, 1] + 15 w[1, 2, h]

foo[example, w | v, h, 3]


20 v[0, 0, h, 0] + v[1, 1, h, 1] + 15 w[1, 2, h]

• Thanks for this solution. For my problem it is overkill, but it uses some really fancy tricks which i would like to understand and which might be useful in near future. I have a problem understanding how you get the parameter from the function all with your a and Pattern, could you maybe explain that idea a bit please? Thanks a lot! – Mario Krenn Dec 29 '16 at 15:17
• @NicoDean, a: v[___] is the pattern v[___] with the assigned name a; so a[[p]] gives Part p of it. In the simpler version in the update the part p of the pattern v[x__] is obtained using v[x][[p]]. Although it is not explicitly stated in the documentation, but Part is not restricted to List objects only; it can be also used for expressions other than lists. Try, for example, g[x,y,z,w][] and g[x,y,z,w][[{2}]] Hope this helps. – kglr Dec 30 '16 at 19:20
expr = Module[{data},
data = RandomInteger[{1, 10}, {3, 5}];
Total[First[#] v[Sequence @@ Rest@#] & /@ data]]


9 v[5, 3, 3, 3] + v[8, 2, 9, 1] + 2 v[8, 5, 3, 1]

Capturing argument i with the help of Repeated pattern object.

inc[i_ /; 1 <= i <= 4] :=
a_. v[x : Repeated[_, {i - 1}], y_, z___] :> a y v[x, y + 1, z]

expr /. inc


27 v[5, 3, 4, 3] + 9 v[8, 2, 10, 1] + 6 v[8, 5, 4, 1]