MathGroup Archive 2009

[Date Index] [Thread Index] [Author Index]

Search the Archive

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?