鸟群的动力学模型(Boids model)

在这里插入图片描述
在这里插入图片描述

import numpy as np

class Boids:
    def __init__(self, Np, Na, home=[0,0]):
        self.Np = Np  # predator
        self.Na = Na  # agent
        self.d = len(home)
        self.home = np.array(home)
        self.predators = np.random.random((Np, self.d*2)) 
        self.agents = np.random.random((Na, self.d*2))
        self.radius_repulsion = 1
        self.radius_alignment = 0.1
        
    def _pairwise_distances(self, X, Y):
        D = -2 * X @ Y.T + np.sum(Y ** 2, axis=1) + np.sum(X ** 2, axis=1)[:, np.newaxis]
        D[D < 0] = 0
        return D
        
    def _force(self):
        Daa = self._pairwise_distances(self.agents[:,:self.d], self.agents[:,:self.d])
        Dap = self._pairwise_distances(self.agents[:,:self.d], self.predators[:,:self.d])

        Neibors_repulsion = (Daa < self.radius_repulsion).astype(int)
        Neibors_alignment = (Daa < self.radius_alignment).astype(int)
        
        Dr = (1/(Daa+np.eye(self.Na))) * Neibors_repulsion
        Fr = np.diag(np.sum(Dr, axis=1))@ self.agents[:,:self.d] - Dr @ self.agents[:,:self.d]

        Fh = self.home - self.agents[:,:self.d]
    
        Fa = Neibors_alignment @ self.agents[:,self.d:] - 2*self.agents[:,self.d:]
        
        s = 100
        Ff = -np.diag(np.sqrt(np.sum(np.square(self.agents[:,self.d:]), axis=1))- s)/s @ self.agents[:,self.d:]
        
        F_total = Fr + 5*Fh + Ff + Fa
        return 200 * np.tanh(0.1*F_total)
        
    def evolve(self, dt = 0.01):
        self.agents[:,self.d:] += dt*self._force()
        self.agents[:,:self.d] += dt*self.agents[:,self.d:]
        
Na = 30
d = 2
n_history = 10
film = np.zeros((Na, d*n_history))
boids = Boids(0, Na)    
for t in range(100):        
    boids.evolve()
    film = np.hstack([boids.agents[:,:d], film[:,:-d]])
    if t > n_history:
        plt.figure()
        for i in range(Na):
            plt.plot(film[i,0],film[i,1], 'ko')
            plt.plot(film[i,::2],film[i,1::2], 'k-',alpha=0.5)
        bound = 3
        plt.xlim([-bound,bound])
        plt.ylim([-bound,bound])
        plt.title('t={}'.format(t))
        plt.savefig('../fig/{}.jpg'.format(t))
        plt.show()

在这里插入图片描述

如果没有 F f F_f Ff 和外部干扰时,会达到平衡状态,如上图

加入 F f F_f Ff项后,群体速度不会变为 0,

在这里插入图片描述

加入捕食者

在这里插入图片描述

import numpy as np

class Boids:
    def __init__(self, Na, home=[0,0], initial_bound=1):
        self.Na = Na  # agent
        self.d = len(home)
        self.home = np.array(home)
        self.agents = (np.random.random((Na, self.d*2))-0.5)*initial_bound*2
        self.radius_repulsion = 1
        self.radius_alignment = 0.1
        self.radius_repulsion_predator = 10
        self.predators = None
        
    def _pairwise_distances(self, X, Y):
        D = -2 * X @ Y.T + np.sum(Y ** 2, axis=1) + np.sum(X ** 2, axis=1)[:, np.newaxis]
        D[D < 0] = 0
        return D
    
    def set_predators(self, locations):
        self.predators = locations
        
    def _force(self):
        Daa = self._pairwise_distances(self.agents[:,:self.d], self.agents[:,:self.d])
        Neibors_repulsion = (Daa < self.radius_repulsion).astype(int)
        Neibors_alignment = (Daa < self.radius_alignment).astype(int)
        
        Dr = (1/(Daa+np.eye(self.Na))) * Neibors_repulsion
        Fr = np.diag(np.sum(Dr, axis=1))@ self.agents[:,:self.d] - Dr @ self.agents[:,:self.d]
        
        if self.predators is not None:
            Dap = self._pairwise_distances(self.agents[:,:self.d], self.predators[:,:self.d])
            Predator_repulsion = (Dap < self.radius_repulsion_predator).astype(int)      
            Dp = (1/Dap) * Predator_repulsion
            Fp = np.diag(np.sum(Dp, axis=1))@ self.agents[:,:self.d] - Dp @ self.predators[:,:self.d]
        else:
            Fp = 0
        
        Fh = self.home - self.agents[:,:self.d]
    
        Fa = Neibors_alignment @ self.agents[:,self.d:] - 2*self.agents[:,self.d:]
        
        s = 5
        Ff = -np.diag(np.sqrt(np.sum(np.square(self.agents[:,self.d:]), axis=1))- s)/s @ self.agents[:,self.d:]
        
        F_total = 0.5*Fr + 10*Fh + Ff + Fa + 10*Fp
        return 200 * np.tanh(0.1*F_total)
        
    def evolve(self, dt = 0.01):
        self.agents[:,self.d:] += dt*self._force()
        self.agents[:,:self.d] += dt*self.agents[:,self.d:]
        
Na = 30
d = 2
n_history = 10
film = np.zeros((Na, d*n_history))
predator = 0.5*np.array([[np.sin(0.1*t),np.cos(0.1*t)] for t in range(100)])
boids = Boids(Na)    
for t in range(100):
    boids.set_predators(predator[t:t+1])
    boids.evolve()
    film = np.hstack([boids.agents[:,:d], film[:,:-d]])
    if t > n_history:
        plt.figure()
        plt.plot(predator[t,0], predator[t,1],'ro')
        plt.plot(predator[t-n_history:t,0], predator[t-n_history:t,1],'r-',alpha=0.5)
        for i in range(Na):
            plt.plot(film[i,0],film[i,1], 'ko')
            plt.plot(film[i,::2],film[i,1::2], 'k-',alpha=0.5)
        bound = 3
        plt.xlim([-bound,bound])
        plt.ylim([-bound,bound])
        plt.title('t={}'.format(t))
        plt.savefig('../fig/{}.jpg'.format(t))
        plt.show()

在这里插入图片描述

参考文献

@article{1987Flocks,
  title={Flocks, Herds and Schools: A Distributed Behavioral Model},
  author={ Reynolds, C. W. },
  journal={ACM SIGGRAPH Computer Graphics},
  volume={21},
  number={4},
  pages={25-34},
  year={1987},
}

@article{doi:10.1063/5.0039745,
author = {Lymburn,Thomas  and Algar,Shannon D.  and Small,Michael  and Jüngling,Thomas },
title = {Reservoir computing with swarms},
journal = {Chaos: An Interdisciplinary Journal of Nonlinear Science},
volume = {31},
number = {3},
pages = {033121},
year = {2021},
doi = {10.1063/5.0039745},
}
  • 4
    点赞
  • 0
    评论
  • 3
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

打赏
文章很值,打赏犒劳作者一下
相关推荐
©️2020 CSDN 皮肤主题: 程序猿惹谁了 设计师:白松林 返回首页

打赏

颹蕭蕭

白嫖?

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者