Re: 3D Agent Problem

• To: mathgroup at smc.vnet.net
• Subject: [mg99006] Re: [mg98979] 3D Agent Problem
• From: Daniel Lichtblau <danl at wolfram.com>
• Date: Fri, 24 Apr 2009 03:44:14 -0400 (EDT)
• References: <200904231042.GAA24510@smc.vnet.net>

```Earl.J.Mitchell at gmail.com wrote:
> Hi,
>
> I am trying to set up a 3D environment having 'agents' and 'stuff' whose
> coordinates are random real numbers.
>
> The program should then move the agents towards the closest stuff in
> increments of, say, .1 units.
>
> I was able to create a program that did what I need for one iteration, but
> am having problems making it iterative... below is the code. I'm
> inexperienced and learning quickly but would really appreciate any guidance
> on iterating this system.
>
> *****************
> Making a World of Agents and Stuff
>
> MakeNewWorld[Agents_] :=
> Partition[Flatten[
> Riffle[Table[RandomReal[{-10, 10}, {Agents, 3}]],
> Table[RandomInteger[9, 3], {Agents}]]], 6, 6]
>
> MakeNewStuff[Resources_] := Table[RandomReal[{-10, 10}, {Resources, 3}]]
>
> agentpos1 = MakeNewWorld[10][[All, 1 ;; 3]];
> stuffpos1 = MakeNewStuff[5];
>
> ListPointPlot3D[{agentpos1, stuffpos1 }, PlotStyle -> PointSize[Large]]
>
> ***** 3D plot of agent positions and stuff positions *******
>
> The Problem of Movement
>
> Agents search for nearest stuff and move along the vector between their
> current position and that of the stuff.
>
> Ax = agentpos1[[All, 1]];
> Bx = stuffpos1[[All, 1]];
> Ay = agentpos1[[All, 2]];
> By = stuffpos1[[All, 2]];
> Az = agentpos1[[All, 3]];
> Bz = stuffpos1[[All, 3]];
>
> dx = Part[Ax, #] - Bx &;
> dy = Part[Ay, #] - By &;
> dz = Part[Az, #] - Bz &;
>
> TOTdx = dx /@ {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
> TOTdy = dy /@ {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
> TOTdz = dz /@ {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
>
> squared = #^2 &;
>
> distance = (squared /@ TOTdx + squared /@ TOTdy + squared /@ TOTdz)^.5;
>
> mindistance = Min /@ distance;
>
> stufffinder = Flatten[Position[distance, #]] &;
>
> stuffpositions = Flatten[stufffinder ] /@ mindistance;
>
> newstuff = stuffpositions[[All, 2]];
>
> coords = Part[stuffpos1, #] &;
>
> stuffcoords = coords /@ newstuff;
>
> WalkFunct2 =
> If[Part[Flatten[agentpos1], #] < Part[Flatten[stuffcoords], #],
> Part[Flatten[agentpos1], #] + .5, Part[Flatten[agentpos1], #] - .5] &;
>
> newagentcoords =
> WalkFunct2 /@ {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17,
> 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30};
>
> agentpos2 = Partition[newagentcoords, 3, 3, {1, 3}];
>
> ListPointPlot3D[{agentpos2, stuffpos1 }, PlotStyle -> PointSize[Large]]
>

You are making this more complicated than necessary by focussing on
breaking apart things into coordinates rather than operating on the
lists as entire entities. Also some of the initialization code suffers
from a bit of funk. I instead proceed as below.

makeNewWorld[agents_] :=
Apply[Join,
Partition[
Riffle[RandomReal[{-10, 10}, {agents, 3}],
RandomInteger[9, {agents, 3}]], 2], 1]

makeNewStuff[resources_] := RandomReal[{-10, 10}, {resources, 3}]

agentlocations = makeNewWorld[10][[All, 1 ;; 3]];
stufflocations = makeNewStuff[5];

To iterate the incremental moves you could use NestList. One way to code
this is shown below. Notice that all the action takes place in just a
few lines.

steplist =
NestList[Function[{ll}, (distances =
Outer[Norm[#1 - #2] &, ll, stufflocations, 1];
stuffpositions = Map[First[Ordering[#, 1]] &, distances];
stuffcoords = stufflocations[[stuffpositions]];
steps = .1*Sign[stuffcoords - ll];
ll + steps)], agentlocations, 60];

This next provides a simple way to vislauize the incremental moves as
agents approach stuff.

Manipulate[
ListPointPlot3D[{steplist[[j]], stufflocations},
PlotStyle -> PointSize[Large]], {j, 1, Length[steplist], 1}]

Note that our incremental moves have discrete size of 0.1 and so we
eventually get to locations where agents will step back and forth in the
vicinity of the stuff. I assume this is the sort of thing you intend to
refine later.

Speaking of refinements, it might get quite interesting if agents also
sense proximity of other agents, so they can adjust their notion of
"nearest" to maybe move toward things that are not objects of great
desire. (Okay, this would NEVER happen in the real world...)

By the way, that NestList can be compactified, though doing so makes it
ever the more difficult to follow. Anyway, for those who like such
things, the variant below works.

steplist = NestList[# + Sign[
stufflocations[[Map[First[Ordering[#, 1]] &,
Outer[Norm[#1 - #2] &, #, stufflocations, 1]]]] - #]/10. &,
agentlocations, 60];

I'd imagine one could squeeze still further. The main reason to do this
is to avoid use of global variables, and a cleaner approach would be to
skip compactification and put the whole mess inside a Module.

Daniel Lichtblau
Wolfram Research

```

• Prev by Date: Re: Re: Help with Speeding up a For loop
• Next by Date: Re: Change Figure according to Session Time
• Previous by thread: 3D Agent Problem
• Next by thread: Bug in Rational arithmetic?