swarm-support
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Swarm-Support] Questions about passing SwarmObjects within other object


From: Paul Thompson
Subject: [Swarm-Support] Questions about passing SwarmObjects within other objects
Date: Wed, 8 Sep 2004 16:12:42 -0400

I'm Paul Thompson, a graduate student at Rochester Institute of
Technology.  I'm currently utilizing (or at least trying to) Swarm to
write an simulation for my masters' thesis.

This is a relatively long post/question, and I'd be really grateful to
anyone who would be willing to READ through it, much less ANSWER my
questions :)

I'll give a brief overview of my project, then I'll talk about the
root of my confusion (in heatbugs, of course), and give details on how
it pertains to my project.

Okay, in a nutshell, I'm trying to develop a new control architecture
for multiagent systems with an idea drawn from self-reconfigurable
robots.  In my simulation, control interactions between agents are
delivered by 'hormones' (in the sense that the response of the
receiving agent is based upon its current state rather than variations
in the message transmitted by other agents).  I will return to this
momentarily.

Below is the oft-perused ObserverSwarm of the heatbugs app.  My
concern is with the variable declaration for world and HeatSpace. 
More precisely, why is world declared as a variable while HeatSpace is
declared as a pointer?

My initial thought was that if HeatSpace wasn't declared as a pointer,
then when a HeatSpace object is passed on to aBug, it would only pass
a copy, and since HeatSpace is a dynamic map, it would be a headache
to reconcile each individual copy to the actual global state.  aBug is
granted access to the specific memory zone hosting the HeatSpace
object.

Now, this reasoning doesn't work with world.  Looking in the source
for heatbugs, it is clear that the bug accesses the world to move
itself from one place to other.  I thought that this would require all
the bugs in the swarm being able to look at ONE world, rather than
multiple copies.  I'd appreciate it if somebody could clear up my
confusion.

 // Heatbugs application. Copyright (c) 1996-2000 Swarm Development Group.
// This library is distributed without any warranty; without even the
// implied warranty of merchantability or fitness for a particular
purpose.
// See file LICENSE for details and terms of copying.

// The Heatbug Model swarm encapsulates all the objects used in the //
simulated heatbug world itself (but not the user interface objects)

#import "Heatbug.h"
#import "HeatSpace.h"
#import <space.h> // Grid2d
#import <objectbase/Swarm.h>

@interface HeatbugModelSwarm: Swarm
{
  int numBugs;                                    // simulation
parameters
  double evaporationRate;
  double diffuseConstant;
  int worldXSize, worldYSize;
  int minIdealTemp, maxIdealTemp;
  int minOutputHeat, maxOutputHeat;
  double randomMoveProbability;

  BOOL randomizeHeatbugUpdateOrder;
  id <ActionGroup> modelActions;                  // scheduling data
structures
  id <Schedule> modelSchedule;
  id actionForEach;                               // for frobbing
randomization

  id <List> heatbugList;                          // list of all the
heatbugs
  id <Grid2d> world;                              // objects
representing
  HeatSpace *heat;                                // the world
}

- getHeatbugList;                                 // access methods into
the
- (id <Grid2d>)getWorld;                          // model swarm. These
methods
- (HeatSpace *)getHeat;                           // allow the model
swarm to
                                                  // be observed.
- (BOOL)toggleRandomizedOrder;                    // method to toggle
the
                                                  // randomization feature
- addHeatbug: (Heatbug *)bug;                     // special method for
demo

+ createBegin: aZone;                             // extra methods you
- createEnd;                                      // provide for Swarms
- buildObjects;
- buildActions;
- activateIn: swarmContext;

@end

In my particular case, my bugs are able to create hormones and
transmit them (in the real world, I'd think that the medium would be
by radio).
I accomplish this by using having a bug pass a hormone on to
HormoneSpace, which places copies on a Discrete2d object, as the
following code demonstrates

- addHormone: (Hormone)h atX: (int)x Y: (int)y {
  int i, j
  int tempX, tempY;
  float range;
  Hormone testHormone;

  for (i = -signalRange; i <= signalRange; i++)
  {
    for (j = -signalRange; j <= signalRange; j++)
    {
      range = sqrt(i*i, j*j);
      if (signalRange >= range)
      {
        tempX = (x + i + spaceSizeX - 1) % spaceSizeX;
        tempY = (y + j + spaceSizeY - 1) % spaceSizeY;
        testHormone = [self getHormoneAtX: tempX Y: tempY]
        if (testHormone = nil)
        {
          testHormone = h;
          [testHormone setStrength: range];
          [nextHormone addObject: testHormone atX: tempX Y: tempY];
        }
        else if (range >= [h getStrength])
        {
          testHormone = h;
          [testHormone setStrength: range];
          [nextHormone addObject: testHormone atX: tempX Y: tempY];
        }
      }
    }

  return self;
}

Now, my question is - does this work, or do all the 'hormones' in this
operation retain the attributes of the last change - that is

[testHormone setStrength: range]

Would I have to actually create (with createBegin/createEnd) each
individual hormone spanning HormoneSpace, and copy the ivars of the
hormone passed on by the bug? - as illustrated by the following
pseudocode

- createEnd
{
  Hormone *aHormone;
  id <List> allHormones;

  (loop through every coordinate spanning the Discrete2d object)
  aHormone = [Hormone createBegin: [self getZone]];
  [nextHormone addObject: aHormone atX: x Y: y];
  (loop end)

  return self;
}

Then in addHormone, I have something like this (skipping the distribution step)

-addHormone: (Hormone)aHormone atX: tempx Y: tempy { Hormone holdHormone;

holdHormone = [nextHormone getObjectatX: tempx, Y: tempy];

[holdHormone setType: [aHormone getType] setStrength: [aHormone getStrength]];

[nextHormone putObject: holdHormone atX: tempx Y: tempy];

return self;
}

This is also essential because I use a method inside the bug to 'pick'
up the hormone at its current spot and put it in its internal hormone
list.  Each bug may react and manipulate its internal hormone list
differently. As shown in the below code

- updateInternalHormones
{
  id <Index> hormoneIndex;
  Hormone tempHormone;
  IsotopeType tempIsotope;
  float decayConstant;
  float tempStrength;

  hormoneIndex = [hormoneList begin: [self getZone]];

  while ((tempHormone = [hormoneIndex next]) != nil)
  {
    tempIsotope = [tempHormone getIsotopeType];

    switch(tempIsotope)
    {
      case drone:
        decayConstant = queenDecayConstant;
        break;
      case spring:
        decayConstant = queenDecayConstant;
        break;
      case summer:
        decayConstant = queenDecayConstant;
        break;
      case fall:
        decayConstant = queenDecayConstant;
        break;
      case winter:
        decayConstant = queenDecayConstant;
        break;
      case foodLow:
        decayConstant = foodLowDecayConstant;
        break;
      case foodFound:
        decayConstant = foodFoundDecayConstant;
        break;
      case foodHere:
        decayConstant = foodHereDecayConstant;
        break;
      case default:
        break;
    }
    
    tempStrength = [tempHormone getStrength]*decayConstant;
        
    if (tempStrength < .1)
    {
      [hormoneIndex remove];
      continue;
    }

    [tempHormone setStrength: tempStrength];
    [hormoneIndex put: tempHormone];
  }
  
  [hormoneIndex drop];
  return self;
}  

Does the manipulations here affect the hormonelist of other bugs?  If
so, then I see the solution as having each bug create a new hormone
and copying the ivars from the hormone in HormoneSpace so that the
copy is its own.

        Last question:  I also created another SwarmObject to represent
'nests'  Inside each nest is a list of bugs that is 'inside'.  Now, I
use the list to actually access the bugs.  Do I need to explicitly
pass the pointer to the bug in question such as:

- enterNest: (Bug *)enteringBug
{

(declaration mumbojumbo deleted)

[nestList addLast: enteringBug];
}

Or would this work?

- enterNest: (Bug)enteringBug
{

(foobar)

[nestList addLast: enteringBug];
}

Precisely, my question is if I create an index for nestList and did
this:

While ((currentBug = [indexNestList next]) != nil) {
  [currentBug doMethod];
}

If I didn't pass the pointer to the bug when adding it to the list,
would the command [currentBug doMethod] act on the state of bug when
it was added to the list, or would it reflect the 'true' state of the
bug?


reply via email to

[Prev in Thread] Current Thread [Next in Thread]