[From Bruce "the animist" Abbott (941104.1500 EST)]
The aliens have completed their work on ECOLI4, and have asked me to transmit
it to Enterprise. As they have explained to me, they found that they were
forced to use some rather complex arrangements in order to demonstrate
discriminated reinforcement/punishment of tumbling behavior. Although they
admit that this is very un-e.-coli-like, they wanted me to point out to the
Enterprise crew that while real e. coli do not learn, more advanced creatures
such as the Funge-wergels of Splorjab occasionally do. ECOLI4 shows the
reinforcement principle at work in a somewhat more complex e. coli that had to
learn what to do in order to approach its nutrients.
As Spock will no doubt quickly discover, ECOLI4 models the three-term
contingency suggested by Sam Saunders, with whom they have been in recent
communication via the csg-l subspace carrier. Tumbling occurs in the presence
of increasing nutrient levels (Tumbling given S+) or decreasing nutrient
levels (Tumbling given S-). On the next tick after a tumble, e. coli
skinnerius determines whether the tumble has resulted in an increasing
nutrient level (Reinforcement) or decreasing nutrient level (Punishment).
These consequences of tumbling then act to alter the probability of tumbling
in the presence of the stimulus that was present during the tumble (S+ or S-).
If tumbling led to increasing nutrients, its probability is decreased; if to
decreasing nutrients, it is increased. [Note: the aliens recognize that this
is opposite to the usual effects of reinforcement and punishment but feel that
selective pressures during evolution would have produced this unique
arrangement, given e. coli's highly restricted response capabilities. The
aliens are very good at verbal rationalizations, as you have probably already
noticed.]
Bruce
{***********************************************************************
* E. COLI "REINFORCEMENT" SIMULATION 4 *
* *
* Programmer: Dr. Bruce B. Abbott *
* Psychological Sciences *
* Indiana U. - Purdue U. *
* Fort Wayne, IN 46805-1499 *
* (219) 481-6399 *
* Language: Borland/Turbo Pascal 7.0 *
* Created: 11/03/94 *
* *
* This program implements a "selection-by-consequences" discriminated *
* operant simulation of the "tumble-and-swim" behavior of e. coli. *
* *
***********************************************************************}
program Ecoli4;
uses
CRT, Graph, GrUtils;
const
TWOPI = PI * 2;
ENDSESSION = 10000;
var
MaxX, MaxY: integer;
NutrX, NutrY, X, Y: integer;
NutMag, NutCon, dNut, NutSave: real;
EcoliX, EcoliY,
Speed, Angle, DecayRate, LearnRate,
pTumbleGivenSplus, pTumbleGivenSminus,
pMax, pMin: real;
JustTumbled: boolean;
Ch: char;
Clock: longint;
procedure InitScreen;
begin
ClrScr;
InitGraphics;
MaxX := GetMaxX; MaxY := GetMaxY;
Rectangle(0, 0, MaxX, MaxY);
OutTextXY(MaxX div 2 - 220, Y+5,
'E. COLI SIMULATION # 4: DISCRIMINATED REINFORCEMENT MODEL');
OutTextXY(MaxX - 200, 50, ' dNutrient');
OutTextXY(MaxX - 200, 60, 'p(Tumble|S+)');
OutTextXy(MaxX - 200, 70, 'p(Tumble|S-)');
OutTextXY(20, MaxY-50, 'Press ESC to Quit...');
end;
procedure ShowReal(x,y: integer; v: real);
var s: string;
begin
str(v:8:4, s);
setfillstyle(0,0);
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 2;
NutrY := MaxY div 2;
EcoliX := 50.0;
EcoliY := 50.0;
X := Round(EcoliX);
Y := Round(EcoliY);
Rectangle(NutrX-2, NutrY-2, NutrX+2, NutrY+2);
Speed := 1.0;
DecayRate := 0.25;
LearnRate := 0.005;
JustTumbled := false;
NutSave := 0;
pMax := 0.500; { Maximum tumble rate }
pMin := 0.05; { Minimum tumble rate }
pTumbleGivenSplus := 0.050; { initial tumble rates }
pTumbleGivenSminus := 0.050;
NutMag := 100.0; { max concentration }
repeat Tumble(Angle) until (Angle < PI/2);
Clock := 0;
end;
function NutConcen(X, Y: 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;
procedure ReinforceOrPunish;
begin
If dNut > 0 then { nutrients rising: reinforcement }
begin
If NutSave > 0 then { S+ present when last tumbled }
begin
if pTumbleGivenSplus > pMin then
pTumbleGivenSplus := pTumbleGivenSplus - LearnRate;
end
else { S- present when last tumbled }
begin
if pTumbleGivenSminus > pMin then
pTumbleGivenSminus := pTumbleGivenSminus - LearnRate;
end
end
else { nutrients not rising: punishment }
begin
If NutSave > 0 then { S+ present when last tumbled }
begin
if pTumbleGivenSplus < pMax then
pTumbleGivenSplus := pTumbleGivenSplus + LearnRate;
end
else { S- present when last tumbled }
begin
if pTumbleGivenSminus < pMax then
pTumbleGivenSminus := pTumbleGivenSminus + LearnRate;
end;
end;
end;
procedure DoTumble;
begin
Tumble(Angle);
JustTumbled := true;
NutSave := dNut;
end;
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);
dNut := DecayRate * dNut + (NewNut - NutCon);
if JustTumbled then ReinforceOrPunish;
if dNut > 0 then { Nurients increasing }
begin
if (Random < pTumbleGivenSplus) then DoTumble
else JustTumbled := false;
end
else { Nutrients stable or decreasing }
begin
if (Random < pTumbleGivenSminus) then DoTumble
else JustTumbled := false;
end;
NutCon := NewNut;
showreal(maxx - 100, 50, dNut);
showreal(maxx - 100, 60, pTumbleGivenSplus);
showreal(maxx - 100, 70, pTumbleGivenSminus);
end;
var i: integer;
z: real;
begin
InitScreen;
InitSim;
repeat
inc(Clock);
StepEcoli;
outtextxy(1,1, '');
if Keypressed then Ch := ReadKey;
until (Ch = #27) or (Clock >= ENDSESSION);
if Ch <> #27 then Ch := ReadKey;
RestoreCRTMode;
CloseGraph;
end.