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$

3 Answers 3

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$
5
  • $\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$ Commented Dec 28, 2016 at 18:49
  • $\begingroup$ Glad you like it! $\endgroup$
    – corey979
    Commented Dec 28, 2016 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$ Commented Dec 28, 2016 at 18:59
  • $\begingroup$ @J.M. Ha! I had a feeling something is way too complicated here. Thanks. $\endgroup$
    – corey979
    Commented Dec 28, 2016 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
    Commented Dec 28, 2016 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$
2
  • $\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$ Commented Dec 29, 2016 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
    Commented Dec 30, 2016 at 19:20
2
$\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 and acknowledge you have read our privacy policy.

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