My source code

[From Bill Powers (2008.09.30.1058 MDT)]

Hello, Bo Wang --

I'm sending this to CSGnet because others will be interested in your Java code.

I'm working on the source code you sent me and am a long way from understanding it, so please forgive me if I am misinterpreting how it works.

I'm looking at the Person.java file. In the "reorganization()" function I find this section:

···

===========================================================================
destp_vel += REORG_GAIN * wgts[0] * rgain[0] * DestProx.ie
        * Math.abs(DestProx.e) * dt;
    destp_dir += REORG_GAIN * wgts[1] * rgain[1] * DestProx.ie
        * Math.abs(DestProx.e) * dt;

    destd_vel += REORG_GAIN * wgts[2] * rgain[2] * DestDir.ie
        * Math.abs(DestDir.e) * dt;
    destd_dir += REORG_GAIN * wgts[3] * rgain[3] * DestDir.ie
        * Math.abs(DestDir.e) * dt;

    avodp_vel += REORG_GAIN * wgts[4] * rgain[4] * AvoidProx.ie
        * Math.abs(AvoidProx.e) * dt;
    avodp_dir += REORG_GAIN * wgts[5] * rgain[5] * AvoidProx.ie
        * Math.abs(AvoidProx.e) * dt;

    avodd_vel += REORG_GAIN * wgts[6] * rgain[6] * (AvoidDir.ie + 0.1)
        * Math.abs(AvoidDir.e) * dt;
    avodd_dir += REORG_GAIN * wgts[7] * rgain[7] * (AvoidDir.ie + 0.1)
        * Math.abs(AvoidDir.e) * dt;

The output weights wgts[i] are applied here to determine the amount of effect each error signal (multiplied by other factors too) has on velocity or direction. This appears to be done correctly.

Now looking in the function "tumble()" we have this:

===================================================================
  random_angle = (Math.random() - 0.5) * 2 * Math.PI;

      wgts[i] = prefix * Math.cos(random_angle);
      prefix *= Math.sin(random_angle);

From this it seems that when a reorganization occurs, the output weights are given new values chosen at random in the range from -1.0 to 1.0.

If this is correct, then we do NOT have E. coli reorganization here.

In E. coli reorganization, the weights are changed on EVERY ITERATION by a small amount. For each weight wgts[i] there should be a corresponding "direction" vector dwts[i], so on every iteration we have

    wgts[i] += dwts[i]; // see later for more details

As long as the vector dwts[] is not changed, the result is that the point wgts[] moves in a specific direction in hyperspace, equivalent to E. coli swimming in a straight line. A tumble should change dwts[], not wgts[].

I think that reorganizations ("tumbles") are determined here:

===============================================================================
if (TEST_INTV < acctime) {
      acctime = 0;
      recordPos();

      if ((destp_intg >= last_destp_intg)
          >> (destd_intg >= last_destd_intg)
          >> (avodp_intg >= last_avodp_intg)
          >> (avodd_intg >= last_avodd_intg))
        tumble();

      last_destp_intg = destp_intg;
      destp_intg = 0;
      last_destd_intg = destd_intg;
      destd_intg = 0;
      last_avodp_intg = avodp_intg;
      avodp_intg = 0;
      last_avodd_intg = avodd_intg;
      avodd_intg = 0;
                    }

If so, this is not quite right, because it is neither "local" nor "global" reorganization.

For local reorganization, if the new absolute value of error (for example, destd_intg) is greater than the old value in only one system, then only the direction value for that system should tumble.

For global reorganization, if the SUM OF ALL absolute errors is larger than the previous value, then ALL of the direction values should tumble.

The way you have it, if there is an increase in any one of the absolute errors, then all of the systems tumble -- even if the errors in the other three systems are decreasing. This is not what you want, because the total error might still be decreasing; in general, either you use local error detection and reorganize ONLY the system with increased error, or you use global error detection and reorganize all the systems. Either way, total error will decrease.

What you need to do to obtain true E. coli reorganization is to add, just after this test, a step that adds the direction vectors to the weights:

for (int i=0; i < 8; ++i)
    wgts[i] += dwts[i]*math.abs(X.e);

// where X is the appropriate Dir or Prox structure. So this has to be written with // a switch statement which you can do. Multiplying by the absolute error is needed
// so reorganization will slow down as zero error is approached.

Whether or not there is a reorganization, the direction vector values are added to the corresponding weights on every iteration. The direction numbers, of course, should be very small numbers, on the order of 1e-6 to 1e-3 (or whatever works right in this case).

Also, you need to change the tumble() function so instead of assigning the random weights to wgts[i], you assign them to dwts[i], the vector of direction numbers.
You can also multiply the dwts[] entries by the overall reorganization gain factor so that multiplication doesn't have to be done so often. The direction numbers should not be angles; just scalar numbers, since they will add to the weights directly.

Now as the weights change, the errors will get larger (producing a tumble) or smaller (resulting in no tumble). If the errors are getting smaller, the same direction numbers will continue to be added, changing the weights along the same line in hyperspace. When the closest approach to the optimum weight settings is passed, the error will get larger and a tumble will occur. Notice that this "direction" has nothing to do with the direction the objects move in space. It's a direction in the 8-dimensional space of the weights.

I recommend that you remove the "attention" feature for now and just get the E. coli reorganization working properly. When that is working, you can experiment with the effect of attending where the errors are greatest -- though you may find that the E. coli method does that automatically!

Best,

Bill P.