第42行: |
第42行: |
| | | |
| Boids 模型已经被用于其他有趣应用。该系统已应用于互联网多频道广播电台的自动节目编排,它也被用于可视化信息和优化任务。<ref>{{cite conference| title= DJ-boids: emergent collective behavior as multichannel radio station programming| first1 = Jesús | last1 = Ibáñez| first2 = Antonio F. | last2 = Gómez-Skarmeta| first3 = Josep | last3 = Blat| date = 2003| booktitle = Proceedings of the 8th international conference on Intelligent User Interfaces| pages = 248–250| doi= 10.1145/604045.604089}}</ref>以及可视化信息<ref>{{cite conference| title= Time-Varying Data Visualization Using Information Flocking Boids| last = Moere | first = A V| date= 2004| booktitle = Proceedings of the IEEE Symposium on Information Visualization| pages= 97–104| doi= 10.1109/INFVIS.2004.65}}</ref>和优化任务。<ref>{{cite journal|first1 = Zhihua | last1 = Cui|first2 = Zhongzhi | last2 = Shi|title= Boid particle swarm optimisation|journal= International Journal of Innovative Computing and Applications|volume=2 |issue=2 |pages= 77–85|date=2009|doi= 10.1504/IJICA.2009.031778}}</ref> | | Boids 模型已经被用于其他有趣应用。该系统已应用于互联网多频道广播电台的自动节目编排,它也被用于可视化信息和优化任务。<ref>{{cite conference| title= DJ-boids: emergent collective behavior as multichannel radio station programming| first1 = Jesús | last1 = Ibáñez| first2 = Antonio F. | last2 = Gómez-Skarmeta| first3 = Josep | last3 = Blat| date = 2003| booktitle = Proceedings of the 8th international conference on Intelligent User Interfaces| pages = 248–250| doi= 10.1145/604045.604089}}</ref>以及可视化信息<ref>{{cite conference| title= Time-Varying Data Visualization Using Information Flocking Boids| last = Moere | first = A V| date= 2004| booktitle = Proceedings of the IEEE Symposium on Information Visualization| pages= 97–104| doi= 10.1109/INFVIS.2004.65}}</ref>和优化任务。<ref>{{cite journal|first1 = Zhihua | last1 = Cui|first2 = Zhongzhi | last2 = Shi|title= Boid particle swarm optimisation|journal= International Journal of Innovative Computing and Applications|volume=2 |issue=2 |pages= 77–85|date=2009|doi= 10.1504/IJICA.2009.031778}}</ref> |
| + | |
| + | ==代码实现== |
| + | 以下内容是使用BOIDS三层模型对鸟群运动进行了模拟,可以通过调节不同的参数获取到不同的实验现象,可以在这个基础上修改模型规则,以更好的模拟集群运动,本文提供一个模板。代码来源是[https://www.cnblogs.com/zhangqifire/p/6621441.html 沐雨橙风fire]所写的博客。 |
| + | |
| + | <source lang="python"> |
| + | |
| + | # -*- coding:utf-8 -*- |
| + | import argparse |
| + | import math |
| + | import numpy as np |
| + | import matplotlib.pyplot as plt |
| + | import matplotlib.animation as animation |
| + | from scipy.spatial.distance import squareform, pdist |
| + | from numpy.linalg import norm |
| + | |
| + | width, height = 1920, 1080 |
| + | |
| + | N = 100 # number of birds |
| + | minDist = 100.0 # min dist of approach |
| + | maxRuleVel = 0.3 # max magnitude of velocities calculated by "rules" |
| + | maxVel = 3.0 # max magnitude of final velocity |
| + | |
| + | |
| + | class Birds: |
| + | """ |
| + | Simulates flock behaviour of birds, using the realistic-looking Boids model (1986) |
| + | """ |
| + | def __init__(self): |
| + | self.N = N |
| + | self.minDist = minDist |
| + | self.maxRuleVel = maxRuleVel |
| + | self.maxVel = maxVel |
| + | |
| + | # Computing initial position and velocity |
| + | self.pos = [width / 2.0, height / 2.0] + 10 * np.random.rand(2 * N).reshape(N, 2) |
| + | # Create an array of N random variable angles in the range [0. 2pi] |
| + | angles = 2 * math.pi * np.random.rand(N) |
| + | # Random velocity vector [x,y] coordinates zip grouped |
| + | self.vel = np.array(list(zip(np.sin(angles), np.cos(angles)))) |
| + | def savef(self): |
| + | with open("douban.txt", "a") as f: |
| + | f.write(str(self.pos.reshape(1, N*2))) |
| + | print str(self.pos.reshape(1, N*2)) |
| + | f.close() |
| + | def tick(self, frameNum, pts, beak): |
| + | """ |
| + | Update the simulation by one time step |
| + | """ |
| + | # get pairwise distances |
| + | self.distMatrix = squareform(pdist(self.pos)) |
| + | # apply rules: |
| + | self.vel += self.apply_rules() |
| + | self.limit(self.vel, self.maxVel) |
| + | self.pos += self.vel |
| + | self.apply_bc() |
| + | # update data |
| + | pts.set_data(self.pos.reshape(2 * self.N)[::2], |
| + | self.pos.reshape(2 * self.N)[1::2]) |
| + | vec = self.pos + 10 * self.vel / self.maxVel |
| + | beak.set_data(vec.reshape(2 * self.N)[::2], |
| + | vec.reshape(2 * self.N)[1::2]) |
| + | self.savef() |
| + | #print self.pos.reshape(2 * self.N) |
| + | #np.savetxt("x.txt", self.pos.reshape(1, 2*N)) |
| + | def limit_vec(self, vec, max_val): |
| + | """ Limit magnitude of 2D vector """ |
| + | mag = norm(vec) |
| + | if mag > max_val: |
| + | vec[0], vec[1] = vec[0] * max_val / mag, vec[1] * max_val / mag |
| + | |
| + | def limit(self, x, max_val): |
| + | """ Limit magnitide of 2D vectors in array X to maxValue """ |
| + | for vec in x: |
| + | self.limit_vec(vec, max_val) |
| + | |
| + | def apply_bc(self): |
| + | """ Apply boundary conditions """ |
| + | deltaR = 2.0 |
| + | for coord in self.pos: |
| + | if coord[0] > width + deltaR: |
| + | coord[0] = - deltaR |
| + | if coord[0] < - deltaR: |
| + | coord[0] = width + deltaR |
| + | if coord[1] > height + deltaR: |
| + | coord[1] = - deltaR |
| + | if coord[1] < - deltaR: |
| + | coord[1] = height + deltaR |
| + | |
| + | def apply_rules(self): |
| + | # apply rule #1 - Separation |
| + | D = self.distMatrix < 20.0 |
| + | vel = self.pos * D.sum(axis=1).reshape(self.N, 1) - D.dot(self.pos) |
| + | self.limit(vel, self.maxRuleVel) |
| + | |
| + | # different distance threshold |
| + | D = self.distMatrix < 50.0 |
| + | |
| + | # apply rule #2 - Alignment |
| + | vel2 = D.dot(self.vel) |
| + | self.limit(vel2, self.maxRuleVel) |
| + | vel += vel2 |
| + | |
| + | # apply rule #1 - Cohesion |
| + | vel3 = D.dot(self.pos) - self.pos |
| + | self.limit(vel3, self.maxRuleVel) |
| + | vel += vel3 |
| + | |
| + | return vel |
| + | |
| + | |
| + | def tick(frameNum, pts, beak, birds): |
| + | """ Update function for animation """ |
| + | birds.tick(frameNum, pts, beak) |
| + | return pts, beak |
| + | |
| + | |
| + | def main(): |
| + | print('Starting flock simulation...') |
| + | |
| + | # Create birds |
| + | birds = Birds() |
| + | |
| + | # Setup plot |
| + | fig = plt.figure() |
| + | ax = plt.axes(xlim=(0, width), ylim=(0, height)) |
| + | pts, = ax.plot([], [], markersize=10, c='k', marker='o', ls='None') |
| + | beak, = ax.plot([], [], markersize=4, c='r', marker='o', ls='None') |
| + | anim = animation.FuncAnimation(fig, tick, fargs=(pts, beak, birds), interval=20) |
| + | |
| + | # TODO: add a "button press" event handler to scatter birds |
| + | #anim.save('basic_animation.mp4', fps=30, extra_args=['-vcodec', 'libx264']) |
| + | plt.show(anim) |
| + | if __name__ == '__main__': |
| + | main() |
| + | |
| + | |
| + | </source> |
| + | |
| + | |
| | | |
| ==参见== | | ==参见== |