ECOLI6 (Not again!)

[Bruce Abbott (941105.1800 EST)]

Below is ECOLI6. No, it is not yet another "reinforcement" model, nor does
this one "learn." What it does do is implement a two-level perceptual control
system, of all things. The bottom level is basically the Powers/Marken system
regulating the tumble rate as a function of the rate of change in nutrient
levels as sensed by the organism. The top level controls perceived stored
nutrient levels, attempting to keep them near a reference level of 100 units
by setting the gain of the lower-level system. Nutrients are assumed to be
absorbed from the surrounding medium in proportion to their concentration, and
used up in proportion to e. coli's rate of travel. THIS e. coli seeks out
nutrient sources when it is hungry, and avoids them when it is satiated!

E. coli's environment contains two nutrient sources, both 100 units peak
concentration. Nutrients drop off from both sources with the square of the
distance, so pickings are pretty slim around the edges of the screen.
Readouts in the upper right corner of the screen show the gain of the lower-
level system, e. coli's level of stored nutrient, and the nutrient level
around the organism.

I doubt that real e. coli regulate their behavior according to stored nutrient
levels, but who knows? If they did, I'll bet they'd act like this.

Do I get my CSG membership badge and signal ring yet? (:->]

Bruce

{***********************************************************************
* NUTRIENT REGULATION IN E. COLI *
* *
* Programmer: Dr. Bruce B. Abbott *
* Psychological Sciences *
* Indiana U. - Purdue U. *
* Fort Wayne, IN 46805-1499 *
* (219) 481-6399 *
* *
* Created: 11/05/94 *
* *
* This program simulates the "swim and tumble" behavior of e. coli *
* using a two-level perceptual control system. The bottom level *
* regulates change in nutrient levels by altering the rate of *
* tumbling inversely with the rate of change of sensed nutrient. *
* The direction of e. coli's travel after tumbling is random. *
* *
* The second level regulates the gain of the first-level system *
* according to the e. coli's level of stored nutrients relative to *
* a reference level of 100 units. E. coli is assumed to absorb the *
* nutrients around it at a rate proportional to nutrient *
* concentration, and to use up nutrients at a rate proportional to *
* its speed. *
* *
* The environment of e. coli contains two food sources indicated by *
* small rectangles. Nutrient level is 100 at each source, but *
* decreases with the square of the radial distance from each source. *
* Thus, as e. coli wanders away from these sources, the level of *
* nutrient in its vicinity drops off rapidly. *
* *
***********************************************************************}

program Ecoli6;

uses
  CRT, Graph, GrUtils;

const
  TWOPI = PI * 2;
  ENDSESSION = 50000;
var
  MaxX, MaxY, Line: integer;
  NutrX, NutrY, NutrX2, NutrY2,
  X, Y, T, T0, DeltaT, Tmax: integer;
  NutMag, NutCon, dNutRef, dNutError, dNut, Gain,
  AbsorbRate, LossRate: real;
  Fuel, FuelRef: real;
  EcoliX, EcoliY,
  Speed, Angle: real;
  Ch: char;
  Clock: longint;

procedure InitScreen;
begin
  ClrScr;
  InitGraphics;
  SetFillStyle(0,0);
  MaxX := GetMaxX; MaxY := GetMaxY;
  Rectangle(0, 0, MaxX, MaxY);
  OutTextXY(MaxX div 2 - 200, Y+5,
    'E. COLI SIMULATION: REGULATING STORED NUTRIENTS');
  OutTextXY(20, MaxY-75, 'Press ESC to Quit...');
  OutTextXY(MaxX-75, Line+20, 'Gain');
  OutTextXY(MaxX-75, Line+40, 'Stores');
  OutTextXY(MaxX-75, Line+60, 'Nutrient');
end;

procedure ShowReal(x,y: integer; v: real);
var s: string;
begin
str(v:12:2, s);
bar (x,y,x+textwidth(s),y+textheight(s));
outtextxy(x,y,s);
end;

procedure Tumble(var Angle: real);
begin
  Angle := TwoPi * Random;
end;

procedure InitSim;
begin
  Randomize;
  NutrX := MaxX div 3;
  NutrY := MaxY div 2;
  NutrX2 := MaxX - NutrX;
  NutrY2:= NutrY;
  EcoliX := 50.0;
  EcoliY := 50.0;
  X := Round(EcoliX);
  Y := Round(EcoliY);
  Rectangle(NutrX-2, NutrY-2, NutrX+2, NutrY+2);
  Rectangle(NutrX2-2, NutrY2-2, NutrX2+2, NutrY2+2);
  Speed := 1.0;
  NutMag := 100.0; { max concentration }
  dNutRef := 0.00; { Reference rate of change in concentration }
  Tmax := 200;
  T0 := 5;
  T := 0;
  Gain := 500.0;
  FuelRef := 100;
  Fuel := 100;
  AbsorbRate := 0.005;
  LossRate := 0.2;
  repeat Tumble(Angle) until (Angle < PI/2);
  Clock := 0;
end;

function NutConcen(X, Y, NutrX, NutrY: real): real;
{ Nutient concentration at point X, Y: environment function }
var
  Dist: real;
begin
  Dist := Sqrt(Sqr(X - NutrX) + Sqr(Y - NutrY));
  NutConcen := NutMag / (1 + 0.001*(Sqr(Dist)));
end;

procedure StepEColi;
var
  NewNut: real;
begin
  EcoliX := EcoliX + Speed * cos(Angle);
  EcoliY := EcoliY + Speed * sin(Angle);
  X := Round(EcoliX);
  Y := Round(EcoliY);
  PutPixel(X, Y, white);
  NewNut := NutConcen(EcoliX, EcoliY, NutrX, NutrY)
    + NutConcen(EcoliX, EcoliY, NutrX2, NutrY2);
  dNut := NewNut - NutCon;
  DeltaT := Round(Gain * (dNutRef - dNut));
  T := T + T0 + DeltaT;
  if T < 0 then T := 0;
  if T > Tmax then
    begin
      Tumble(Angle);
      T := 0;
    end;
  NutCon := NewNut;
  Fuel := Fuel + AbsorbRate*NutCon - LossRate*Speed;
  if Fuel < 0 then Fuel := 0 else
    if Fuel > 200 then Fuel := 200;
  Gain := 50 * (FuelRef - Fuel);
  If (Clock mod 10 = 0) then
    begin
      ShowReal(MaxX-175, Line+20, Gain);
      ShowReal(MaxX-175, Line+40, Fuel);
      ShowReal(MaxX-175, Line+60, NewNut);
    end;
end;

var i: integer;
    z: real;
begin
  InitScreen;
  InitSim;
  repeat
    inc(Clock);
    StepEcoli;
    Delay(5);
    if Keypressed then Ch := ReadKey;
  until (Ch = #27) or (Clock >= ENDSESSION);
  if (Ch <> #27) then Ch := ReadKey;
  RestoreCRTMode;
  CloseGraph;
end.

Tom Bourbon [941107.1750]

[Bruce Abbott (941105.1800 EST)]

Below is ECOLI6.

Bruce, I finally got to test this one and it ran about three times (I had
to stop to re-compile after each run), then it began to hang up with
an error message of a floating point error at

DeltaT := Round(Gain * (dNutRef - dNut));

I'll try to see if I can spot the problem. It may be that not everything is
downward compatible from your Turbo PASCAL 7.0 to my 6.0.

[From Bruce Abbott (941107.1215 EST)]

Tom Bourbon --

I'm sorry I have not been able to respond to your last couple of messages
in a timely fashion; each time I send out a post I get three sets of
responses and it is getting a bit difficult to keep up.

That ought to teach you not to tangle with NCC-1701. :wink:

I will try to get to these within the next day or so.

Not to worry. I've been pinned down on this end and have barely had time to
play catch up reading the mail each day.

Later,

Tom