# How to modify a particular step length in a 3D random walk?

Suppose I simulate a random walk in 3D using AnglePath3D[]:

nTimeSteps = 5;

myRandomWalk = AnglePath3D[RandomReal[{-360 \[Degree], 360 \[Degree]}, {nTimeSteps, 3}]];

Graphics3D[{{Purple, PointSize[0.015],
Point[myRandomWalk]}, {Line[myRandomWalk]}}]


Usually, the step length in a random walk is set from the beginning to some value/variable (default to 1 in the code above). However, for my application, I need to change the length of one of the steps after the simulation is done, to increase it or decrease it some $$\Delta l$$ length, while preserving the angles/proportions of the rest of the random walk (i.e. no rotation, no change in angles, etc). Note that I'd only know that the $$n^{th}$$ step will have to be extended or contracted after the whole random walk is completed.

How could this be done? Ideally, the change in length ($$\Delta l$$) should be distributed symmetrically along the two sides of the modified segment (i.e. the adjustment would affect the two ends of the line to be contracted/extended, not just one of them). An ideal solution might look like:

myDeltaLength[myRandomWalk_, indexOfStepToChange_, magnitudChange_]:=


Current approach not very efficient. Mainly because I'm not at all familiar with geometric transformations, so probably there are many shortcuts I could take.

My solution currently requires me to first generate all the elements of the random walk separately, and then use that info to change the length of the $$n^{th}$$ step. For instance:

nSteps = 15;
myRotationAngles =
RandomReal[{-360 \[Degree], 360 \[Degree]}, {nTimeSteps + 1, 3}];

(*Calculate whole random walk*)
myRandomWalk = AnglePath3D[myRotationAngles];

(*After done, calculate distances between succesive points*)
myDistances =
Table[EuclideanDistance[myRandomWalk[[i]],
myRandomWalk[[i + 1]]], {i, 1, Length[myRandomWalk] - 1}];

(*Visualize*)
Graphics3D[{{Purple, PointSize[0.015],
Point[myRandomWalk]}, {Line[myRandomWalk]}}]


Now, make a function that changes the length of some particular segment of the walk:

myExtendedRandomWalk[myDistances_, myNthSegmentToChange_, myDeltaChange_,
myRotationAngles_] :=
Graphics3D@
Line@AnglePath3D[
Transpose[{ReplacePart[
myDistances, (myDistances[[myNthPathToChange]] +
myDeltaChange), myNthPathToChange], myRotationAngles}]]


We try changing the $$5^{th}$$ segment by 5 (extending this segment):

myExtendedRandomWalk[myDistances, 5, 5, myRotationAngles]


Which does the trick, but it is quite convoluted, and also it is not symmetrical, because it only extends the segment in the "forward" direction (i.e. towards the next connecting line, not towards both the preceding and succeeding line segments).

Thanks!

• Read the Mathemtica documentation for the built-in: reference.wolfram.com/language/ref/AnglePath3D.html. There is given the built-in option RotationTranslation that can be used to modify the step length for each step: AnglePath3D[{{7, {\[Pi]/2, 0}}, {9, {0, \[Pi]/2}}}, "RotationTranslation"]. 7 and 9 are the step length. This option is used by the AnglePath3D if four parameters are entered. Jul 15 '20 at 6:57
• Have you tried anything? It seems like all you want to do is take all points from an index and to the end of the list and add an offset. Then apply another offset from the start of the list to that index. Based on your previous questions, I feel like this is something you can do. Jul 15 '20 at 7:43
• @C.E. I edited my question with a cheap solution I came up with, but it is not symmetrical. As per your comment, when you say "offset", how can this be applied to both sides of the segment in question? I'm just clueless as to what are the proper arguments for any of the "Translation" functions in MMA (which there seem to be many, and which I'm not really familiar with the geometry). Thanks! Jul 15 '20 at 18:30
• @TumbiSapichu thank you for adding an attempt, it helps to know that the person you're trying to help tried himself first. It certainly worked for me, I just felt motivated to post an answer. Jul 15 '20 at 19:37

SeedRandom[300]
nTimeSteps = 5;
myRandomWalk = AnglePath3D[RandomReal[{-360 \[Degree], 360 \[Degree]}, {nTimeSteps, 3}]];
oldRandomWalk = myRandomWalk;

pt1 = myRandomWalk[[4]];
pt2 = myRandomWalk[[5]];
unitVector = Normalize[pt2 - pt1];
delta = 0.5;
myRandomWalk[[;; 4]] = # - (delta/2) unitVector & /@ myRandomWalk[[;; 4]];
myRandomWalk[[5 ;;]] = # + (delta/2) unitVector & /@ myRandomWalk[[5 ;;]];
Graphics3D[{
Red,
PointSize[Large],
Point[myRandomWalk],
Black,
Line[myRandomWalk],
Thick,
Orange,
Line[oldRandomWalk]
}]