7
$\begingroup$

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[[3]]*v[1,1,1+1,1]+10*v[[3]]*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.

$\endgroup$
11
$\begingroup$
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]

$\endgroup$
  • $\begingroup$ 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! $\endgroup$ – NicoDean Dec 28 '16 at 18:49
  • $\begingroup$ Glad you like it! $\endgroup$ – corey979 Dec 28 '16 at 18:51
  • 2
    $\begingroup$ Array[KroneckerDelta, {4, 4}] is just IdentityMatrix[4], no? And, since you're just extracting the p-th row, then what you actually want is UnitVector[4, p]... $\endgroup$ – J. M. is away Dec 28 '16 at 18:59
  • $\begingroup$ @J.M. Ha! I had a feeling something is way too complicated here. Thanks. $\endgroup$ – corey979 Dec 28 '16 at 19:06
  • 2
    $\begingroup$ (+1) perhaps slightly simpler and more general: ex /. v[a__] :> {a}[[p]] (v @@ ({a} + UnitVector[Length[{a}], p])) $\endgroup$ – kglr Dec 28 '16 at 21:03
4
$\begingroup$

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[2], 0] + v[1, 1, h[1], 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[3]]

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

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

$\endgroup$
  • $\begingroup$ 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! $\endgroup$ – NicoDean Dec 29 '16 at 15:17
  • 1
    $\begingroup$ @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][[2]] and g[x,y,z,w][[{2}]] Hope this helps. $\endgroup$ – kglr Dec 30 '16 at 19:20
1
$\begingroup$
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[3]

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

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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