top of page

捕食者仿真器

  • 231469242
  • 2014年5月2日
  • 讀畢需時 10 分鐘

作者:Toby

QQ:231469242

程序可视化:捕食者和猎物数量关系

1.jpg

程序初始化

2.jpg

程序结束

3.jpg

A.K. Dewdne博士在美国自然科学杂志报告

官网:

http://www.leinweb.com/snackbar/wator/

A.K. Dewdne in Scientific American magazine

Description

WATOR is a simulation of the interaction over time of predator and prey in a small rectangular area. It is a simple program originally described by A.K. Dewdney in Scientific American magazine. The game is to arrange the parameters so the populations are stable when the area is made small.

The program is dependent upon five parameters, plus the size of the rectangular grid. The first parameter is the number of fish, the prey. A fish swims at random to one of the four horizontally or vertically adjacent spaces on the grid, if it is unoccupied. The grid wraps around so a fish can swim off one edge and appear at the opposite edge. The second parameter is the fish breed time. If a fish survives this number of cycles and an open space is available, a new fish is bred. The third parameter is the number of sharks, the predators. A shark eats a fish in an adjacent space on the grid. A shark swims to an open space if there is no adjacent fish. The fourth parameter is the shark starve time. If a shark finds no fish for this number of cycles, it dies. The final parameter is the shark breed time. A shark breeds in the same way as a fish.

If the number of sharks is very small, the fish population will increase quickly and the shark population will soon follow because they find plenty of food. Eventually the fish will become overcrowded and overwhelmed by the large shark population and the fish population will crash. Depending upon the quantity and distribution of sharks at the beginning of the crash, the fish may disappear entirely, the sharks may become isolated and disappear or catastrophe may be narrowly averted.

Studies of small, isolated biological systems that lack diversity have shown similar patterns, though never as simply. The ebb and flow of populations is interesting in itself and there is probably slim evidence to support any particular social or political philosophy.

1999年,A.K. Dewdney博士把一程序发布于美国自然科学杂志。WAT-OR游戏,代码是Java,该程序模拟自然栖息地中“捕食者-猎物”问题。实例是鲨鱼和鱼。 “捕食者-猎物”问题充分体现捕食者与猎物之间相互作用,一组动物构成猎物,一组动物构成食肉动物(捕食者)。模拟结果将展示这两个种群之间动态交互。它代表一种栖息地战争,两个种群为生存而挣扎,存活或发展壮大。通常情况下,这两个群体有固定出生率。猎物通常生育速度比捕食者快,猎物数量不断增长。猎物增加供养了更多捕食者,这反过来会增加捕食者数量。一段时间后,猎物数量减少,之后捕食者因食物减少,达到临界点,数量也随之减少,猎物数量反之又增长,理论上这两个种群数量不断交互增长和衰落。虽然已有公式对捕食者与猎物关系建模,但可以用计算机来模拟这种关系,fun ! 这里用大蟒蛇重构模拟,Java用的代码太多,五百多行代码。。。

import random,pylab

class Island():

"""Island,n*n grid where zero value indicates an unoccupied cell."""

#生成一个n排,n列的点矩阵,矩阵是笛卡尔坐标系,x向右递增,y向上递增,(0,0)是左下角,(9,0)是右下角

#(0,9)是左上角,(9,9)是右上角

#程序输出顺序是从左上角(0,9)开始,(1,9),(2,9)。。。到右下角结尾(9,0)

#岛上空白是数字0,在str显示时被‘.’取代

def __init__(self,n,preyCnt=0,predatorCnt=0,advanced_predator_init=0):

#print "in island init"

self.gridSize=n

self.grid=[]

for i in range(n): #生成一个点矩阵

row=[0]*n #row is a list of zero

self.grid.append(row)

self.initAnimals(preyCnt,predatorCnt,advanced_predator_init)

def __str__(self):

"""string representation for printing.

(0,0)will be in the lower-left corner."""

#print "in island str"

s=""

for j in range(self.gridSize-1,-1,-1): #print row size-1 first

for i in range(self.gridSize): #each row starts at 0

if not self.grid[i][j]:

#print a '.' for empty space

s+="%-2s"%'.'+" " # 字符串负号表示左对齐,这里表示左对齐2个单位

else:

s+="%-2s"%(str(self.grid[i][j]))+" "

s+="\n"

return s

def __repr__(self):

return self.__str__()

def __getitem__(self,a):

#print "in getitem"

#可以通过索引查看岛屿地域,还可以通过赋值语句让动物注册到岛上,更加人性化,比register方法更快

return self.grid[a]

def register(self,animal):

'''register animal with island, i.e.put it at the animal's coordinate'''

#register函数是动物和岛屿交互的桥梁,动物的位置x,y被保存到岛屿笛卡尔坐标系中

#print "in island register"

x=animal.x

y=animal.y

self.grid[x][y]=animal

def size(self):

'''reture the size of island:one dimension'''

#print "in island size"

return self.gridSize

def animal(self,x,y):

#print "in animal check"

if 0<=x<self.gridSize and 0<=y<self.gridSize:

#print "ok"

return self.grid[x][y]

else:

#print "no"

return -1 #outside the land boundary

def initAnimals(self,preyCnt,predatorCnt,advanced_predator_init):

'''put some initial animals on the island'''

cnt=0

#while loop continues until preyCnt unoccupied positions are found

while cnt<preyCnt:

x=random.randint(0,self.gridSize-1)

y=random.randint(0,self.gridSize-1)

if self[x][y]==0: #if not self.animal(x,y):

newPrey=Prey(island=self,x=x,y=y)

cnt+=1

self.register(newPrey)

cnt=0

while cnt<predatorCnt:

x=random.randint(0,self.gridSize-1)

y=random.randint(0,self.gridSize-1)

if self[x][y]==0: #if not self.animal(x,y):

newPred=Predator(island=self,x=x,y=y)

cnt+=1

self.register(newPred)

cnt=0

while cnt<advanced_predator_init:

x=random.randint(0,self.gridSize-1)

y=random.randint(0,self.gridSize-1)

if self[x][y]==0: #if not self.animal(x,y):

new_advanced_Predator=Advanced_Predator(island=self,x=x,y=y)

cnt+=1

self.register(new_advanced_Predator)

def remove(self,animal):

x=animal.x

y=animal.y

self.grid[x][y]=0

def clearAllMovedFlags(self):

'''Animals have a moved flag to indicated that they moved this turn.clear

that we can do next turn动物已经移动旗帜来表示它们在此循环中移动。

清除网格所有动物旗帜,让它们能在下一轮中移动'''

for x in range(self.gridSize):

for y in range(self.gridSize):

if self.grid[x][y]:

self.grid[x][y].clearMovedFlag()

def preyCount(self):

'''count all the prey on the island岛屿猎物统计'''

cnt=0

for x in range(self.gridSize):

for y in range(self.gridSize):

animal=self.animal(x,y)

if animal:

if isinstance(animal,Prey):

cnt+=1

return cnt

def predatorCount(self):

'''count all the predators on the island岛屿捕食者统计'''

cnt=0

for x in range(self.gridSize):

for y in range(self.gridSize):

animal=self.animal(x,y)

if animal:

if isinstance(animal,Predator):

cnt+=1

return cnt

def advanced_predatorCount(self):

cnt=0

for x in range(self.gridSize):

for y in range(self.gridSize):

animal=self.animal(x,y)

if animal:

if isinstance(animal,Advanced_Predator):

cnt+=1

return cnt

def equilibrium(self):

#大自然通过疾病,瘟疫,极端气候和其它因素控制某种族的数量,阻止其无限制发展

size=self.gridSize

total_numbers=size**2

preyCnt = self.preyCount()

predCnt = self.predatorCount()

if preyCnt/float(total_numbers)>0.6:

print"in prey equilibrium"

before_remove_prey_numbers=preyCnt/2 #需要移除的猎物数量

after_remove_prey_cnt=0 #统计核实移除数量是否正确

for x in range(size):

for y in range(size):

animal = self.animal(x,y)

if animal: #如果是动物

if isinstance(animal,Prey): #如果动物是捕食者,则运行eat()方法

animal.island.remove(animal)#移除猎物

before_remove_prey_numbers-=1

after_remove_prey_cnt+=1

if before_remove_prey_numbers<=0:

print "nature has removed:%d"%(after_remove_prey_cnt)

break #有问题,数字不准确,移除是大概值,这里可以解释为随机性或不可预测造成

if predCnt/float(preyCnt)>0.3:

print"in predator equilibrium"

before_remove_pred_numbers=predCnt/3

print "before remove_pred_numbers:%d"%(before_remove_pred_numbers)

after_remove_pred_cnt=0 #统计核实移除数量是否正确

for x in range(size):

for y in range(size):

animal = self.animal(x,y)

if animal: #如果是动物

if isinstance(animal,Predator): #如果动物是捕食者,则运行eat()方法

animal.island.remove(animal)#移除猎物

print "remove predator"

before_remove_pred_numbers-=1

after_remove_pred_cnt+=1

if before_remove_pred_numbers<=0:

print "nature has removed:%d"%(after_remove_pred_cnt)

break #有问题,数字不准确,移除是大概值,这里可以解释为随机性或不可预测造成

class Animal(object):

def __init__(self,island,x=0,y=0,name="A"):

'''initialize the animal's name and their position'''

#print "in animal init"

#最后需要它的名字:moose或wolf

self.island=island

self.name=name

self.x=x

self.y=y

self.moved=False #设置为静止,即未移动状态

self.clockTicked=False #生物钟递减为否

def __str__(self):

#print "in animal str"

return self.name

def __repr__(self):

#print "in animal repr"

return self.__str__()

def position(self):

'''return the coordinates of current position'''

#print 'in animal position'

return self.x, self.y

def checkGrid(self,typeLookingFor=int):

'''look in the 8 direction from the animal's location and return the first

location that presently has an object of the specified type.return 0 if

no such location exists'''

#eat(),move()函数都会用到checkGrid(),把此函数改为随机性

# neighbor offsets

offset = [(-1,1),(0,1),(1,1),(-1,0),(1,0),(-1,-1),(0,-1),(1,-1)]

result = 0

for i in range(len(offset)*8):

random_move=random.randint(0,len(offset)-1)

x=self.x+offset[random_move][0]

y=self.y+offset[random_move][1]

if not 0 <= x < self.island.size() or \

not 0 <= y < self.island.size():

continue

if type(self.island.animal(x,y))==typeLookingFor:

#print "found target"

result=(x,y)

break

return result

def move(self):

'''Move to an open, neighboring position移动到旁边一个空位置 '''

if not self.moved: #如果未移动,则下面程序执行

location = self.checkGrid(int) #寻找空白地

if location:

# print 'Move, %s, from %d,%d to %d,%d'% \

# (type(self),self.x,self.y,location[0],location[1])

self.island.remove(self) # remove from current spot

self.x = location[0] # new coordinates

self.y = location[1]

self.island.register(self) # register new coordinates

self.moved=True #移动标记设置为真,则移动后不会再次移动

def breed(self):

'''breed a new Animal,if there is room in one of the 8 locations, place the

new prey there.otherwise,you have to wait'''

if self.breedClock<=0:

location=self.checkGrid(int)

if location:

self.breedClock=self.breedTime

#print"self.breedClock now return to:",self.breedClock

theClass=self.__class__

newAnimal=theClass(self.island,x=location[0],y=location[1])

self.island.register(newAnimal)

def clearMovedFlag(self):

#让动物移动设置为False,方便下次移动

self.moved=False

self.clockTicked=False

class Prey(Animal):

#每个实例都有自己时钟,用于跟踪繁殖时间。predator还有第二个时钟,用于跟踪挨饿时间。也就是

#说,创建实例需要初始化内部“时钟”。每个实例通过clockTick方法,在每个时排,更新自己的时钟。当他们

#繁殖时钟计数到0时,他们能繁殖。饥饿时钟同理

def __init__(self,island,x=0,y=0,s="O"):

#print"in prey init"

Animal.__init__(self,island,x,y,s)

self.breedClock=self.breedTime #breedClock是时钟,会变化,所以用另一个变量名

def clockTick(self):

'''prey updates only its local breed clock'''

if self.clockTicked==False:

self.breedClock-=1

self.clockTicked=True

class Predator(Animal):

def __init__(self,island,x=0,y=0,s="X"):

#print "in predator init"

Animal.__init__(self,island,x,y,s)

self.breedClock=self.breedTime

self.starveClock=self.starveTime

def move(self):

if not self.moved: #如果未移动,则下面程序执行

offset = [(-1,1),(0,1),(1,1),(-1,0),(1,0),(-1,-1),(0,-1),(1,-1)]

result = 0

for i in range(len(offset)*8):

random_move=random.randint(0,len(offset)-1)

x=self.x+offset[random_move][0]

y=self.y+offset[random_move][1]

#如果x,y超过取值范围,则重新循环

if not 0 <= x < self.island.size() or \

not 0 <= y < self.island.size():

continue

if type(self.island.animal(x,y))==int:

self.island.remove(self) # remove from current spot

self.x =x # new coordinates

self.y =y

self.island.register(self) # register new coordinates

self.moved=True #移动标记设置为真,则移动后不会再次移动

break

if type(self.island.animal(x,y))==Prey:

self.island.remove(self.island.animal(x,y))#删除location上的prey

self.island.remove(self) # remove from current spot

self.x =x # new coordinates

self.y =y

self.island.register(self)#捕食者注册到猎物位置上

self.starveClock=self.starveTime

self.moved=True #移动标记设置为真,则移动后不会再次移动

break

if type(self.island.animal(x,y))==Predator:

continue

def eat(self):

'''predator looks for one of the eight locations with Prey,if found,moves to that location,

updates the starve clock,removes the Prey'''

if not self.moved and self.starveClock<=1:

print "in eat"

location=self.checkGrid(Prey)

if location:

self.island.remove(self.island.animal(location[0],location[1])) #删除location上的prey

self.island.remove(self)#清空捕食者现在位置

self.x=location[0]

self.y=location[1]

self.island.register(self)#捕食者注册到猎物位置上

self.starveClock=self.starveTime

self.moved=True #行为结束后移动设置为True,不会再次移动

def clockTick(self):

#每经历一次事件循环,都需要更新每个实例的当前状态,特别是初始化为类值(繁殖和挨饿时间)的那些个体的时钟必须递减。因此,每

#个类需要一个方法来在每个时钟节拍内更新内部实例的时钟。在每个子类中创建了两个方法,叫clockTick

if self.clockTicked==False:

self.breedClock-=1

self.starveClock-=1

self.clockTicked==True

if self.starveClock<=0:

self.island.remove(self)

def clockTick(self):

#每经历一次事件循环,都需要更新每个实例的当前状态,特别是初始化为类值(繁殖和挨饿时间)的那些个体的时钟必须递减。因此,每

#个类需要一个方法来在每个时钟节拍内更新内部实例的时钟。在每个子类中创建了两个方法,叫clockTick

if self.clockTicked==False:

self.breedClock-=1

self.starveClock-=1

#print "self.starveClock:",self.starveClock

self.clockTicked=True

if self.starveClock<=0:

self.island.remove(self)

class Advanced_Predator(Predator):

def __init__(self,island,x=0,y=0,s="W"):

Predator.__init__(self,island,x,y,s)

self.breedClock=self.breedTime-2

self.starveClock=self.starveTime+2

def eat(self):

if not self.moved:

location=self.checkGrid(Prey)

if location:

self.island.remove(self.island.animal(location[0],location[1])) #删除location上的prey

self.island.remove(self)#清空捕食者现在位置

self.x=location[0]

self.y=location[1]

self.island.register(self)#捕食者注册到猎物位置上

self.starveClock=self.starveTime

self.moved=True #行为结束后移动设置为True,不会再次移动

def main(predBreed=6,predStarve=4,predInit=10,preyBreed=5,preyInit=50,size=15,\

ticks=300,advanced_predator_init=3):

'''main simulation;sets defaults,runs event loop,plots at the end'''

#initialization of the simulation

#1.创建Island实例和一些Predator实例和Prey实例

#2.在指定数量的时间周期内进行循环

# 2.1移动每个实例

#predBreed:Predator实例繁殖前必须经过的时间间隔

#preyBreed:Prey实例繁殖前必须经过的时间间隔

#predStarve: Predator实例必须在此时间间隔中进食,否则会饿死

#preInit:最初放入岛上的Predator实例个数

#preyInit:最初放入岛上的prey实例个数

#Size: Island实例一边的长度(假设岛是一个正方形)

#ticks: 模拟结束前将经过的时间间隔数目

Predator.breedTime=predBreed

Predator.starveTime=predStarve

Prey.breedTime=preyBreed

# for graphing 用于绘图

advanced_predList=[]#每一个时钟高级捕食者数量将放入此列表

#make an island

isle=Island(size,preyInit,predInit,advanced_predator_init)

print "initial prey num:%d,inital predator num:%d,inital advanced_predator num:%d,"%(preyInit,predInit,advanced_predator_init)

print "init isle:"

print isle

#event loop

#for all the ticks,for every x,y location

#if there is an animal there,try eat,move,breed and clockTick

for i in range(ticks):

print "tick%d:"%(i)

isle.equilibrium()

#import to clear all the moved flags!记得清楚所有标记,让moved=False

isle.clearAllMovedFlags()

for x in range(size):

for y in range(size):

animal=isle.animal(x,y)

if animal:

if isinstance(animal,Predator): #如果动物是捕食者,则运行eat()方法

animal.eat()

animal.move() #动物移动

animal.breed() #动物繁殖

animal.clockTick() #动物生物钟递减1,如果捕食者饥饿时钟<0,

#则饿死,从岛上注销

print isle

#record info for display,plotting

preyCnt=isle.preyCount()

predCnt=isle.predatorCount()

Advanced_predCnt=isle.advanced_predatorCount()

print "prey num:%d,predator num:%d,advanced_pred num:%d"%(preyCnt,predCnt,Advanced_predCnt)

if preyCnt==0:

print 'lost the Prey population,quiting'

break

if predCnt==0:

print 'lost the Predator population,quiting'

break

preyList.append(preyCnt)

predList.append(predCnt)

advanced_predList.append(Advanced_predCnt)

#print out every 10th cycle,see what’s going on

if not i%10:

print preyCnt,predCnt,Advanced_predCnt

#print 'preyCnt num:',preyCnt

#print 'predCnt num:',predCnt

#print '*'*20

#print isle

pylab.plot(predList,'r')

pylab.plot(preyList,'b')

pylab.plot(advanced_predList,'y')

pylab.title('predator(red),advanced_predList(yellow), and prey(blue) simulation')

pylab.xlabel('time ticks')

pylab.ylabel('numbers')

pylab.show()

def isle_test():

k=10

grid=[]

S=''

for i in range(k):

row=[0]*k

grid.append(row)

print grid

for j in range(k-1,-1,-1):

for i in range(k):

if not grid[i][j]:

print 'yes'

S+="%-2s"%'.'+''

print S

else:

print 'no'

S+=""%(str(grid[i][j]))

print S

print "grid[%d][%d] is:" %(i,j),grid[i][j]

S+="\n"

def move_test(predBreed=6,predStarve=6,predInit=10,preyBreed=3,preyInit=30,size=10,\

ticks=20):

Prey.breedTime=preyBreed

Predator.breedTime = predBreed

Predator.starveTime = predStarve

#make an island

isle=Island(size,preyInit,predInit)

print "init isle:"

print isle

for i in range(ticks):

print "tick%d:"%(i)

#import to clear all the moved flags!记得清楚所有标记,让moved=False

isle.clearAllMovedFlags()

for x in range(size):

for y in range(size):

#print "x,y:",x,y 主函数遍历测试

animal=isle.animal(x,y)

if animal:

animal.move() #动物移动

animal.clockTick()

#print"breedClock:",animal.breedClock

preyCnt=isle.preyCount()

predCnt=isle.predatorCount()

print "prey num:%d,predator num:%d"%(preyCnt,predCnt)

print isle

def breed_test(predBreed=500,predStarve=500,predInit=0,preyBreed=3,preyInit=1,size=10,\

ticks=10):

#测试成功,纠正了两位教授代码

#Predator.breedTime=predBreed

#Predator.starveTime=predStarve

Prey.breedTime=preyBreed

#make an island

isle=Island(size,preyInit,predInit)

print "initial prey num:%d,predator num:%d"%(preyInit,predInit)

print "init isle:"

print isle

for i in range(ticks):

print "tick%d:"%(i)

#import to clear all the moved flags!记得清楚所有标记,让moved=False

isle.clearAllMovedFlags()

for x in range(size):

for y in range(size):

animal=isle.animal(x,y)

if animal:

animal.move()

animal.breed() #动物繁殖

animal.clockTick() #动物生物钟递减1,如果捕食者饥饿时钟<0,#则饿死,从岛上注销

print"breedClock:",animal.breedClock

preyCnt=isle.preyCount()

predCnt=isle.predatorCount()

print "prey num:%d,predator num:%d"%(preyCnt,predCnt)

print isle

def starve_test(predBreed=6,predStarve=3,predInit=3,preyBreed=3,preyInit=0,size=10,\

ticks=10):

Predator.breedTime=predBreed

Predator.starveTime=predStarve

Prey.breedTime=preyBreed

isle=Island(size,preyInit,predInit)

print "initial prey num:%d,inital predator num:%d"%(preyInit,predInit)

print "init isle:"

print isle

for i in range(ticks):

print "tick%d:"%(i)

#import to clear all the moved flags!记得清楚所有标记,让moved=False

isle.clearAllMovedFlags()

for x in range(size):

for y in range(size):

animal=isle.animal(x,y)

if animal:

if isinstance(animal,Predator):

animal.eat() #如果是捕食者,进食

animal.move() #动物移动

animal.breed() #动物繁殖

animal.clockTick() #动物生物钟递减1,如果捕食者饥饿时钟<0,

#则饿死,从岛上注销

print isle

#record info for display,plotting

preyCnt=isle.preyCount()

predCnt=isle.predatorCount()

print "prey num:%d,predator num:%d"%(preyCnt,predCnt)

def eat_test(predBreed=6,predStarve=3,predInit=1,preyBreed=3,preyInit=99,size=10,\

ticks=10):

Predator.breedTime=predBreed

Predator.starveTime=predStarve

Prey.breedTime=preyBreed

isle=Island(size,preyInit,predInit)

print "initial prey num:%d,inital predator num:%d"%(preyInit,predInit)

print "init isle:"

print isle

for i in range(ticks):

print "tick%d:"%(i)

#import to clear all the moved flags!记得清楚所有标记,让moved=False

isle.clearAllMovedFlags()

for x in range(size):

for y in range(size):

animal=isle.animal(x,y)

if animal:

if isinstance(animal,Predator):

animal.eat() #如果是捕食者,进食

animal.move() #动物移动

animal.breed() #动物繁殖

animal.clockTick() #动物生物钟递减1,如果捕食者饥饿时钟<0,

#则饿死,从岛上注销

print isle

#record info for display,plotting

preyCnt=isle.preyCount()

predCnt=isle.predatorCount()

print "prey num:%d,predator num:%d"%(preyCnt,predCnt)

 
 
 

留言


Featured Posts
Recent Posts
Archive
统计学,数据分析,糖尿病
Follow Us
  • Facebook Basic Square
  • Twitter Basic Square
  • Google+ Basic Square

电话:

15923087684

 

QQ:

231469242

bottom of page