Particle Life粒子生命演化的MATLAB模拟

Particle Life粒子生命演化的MATLAB模拟

  • 0 前言
  • 1 基本原理
    • 1.1 力影响-吸引排斥行为
    • 1.2 距离rmax影响
  • 2 多种粒子相互作用
    • 2.1 双种粒子作用
    • 2.1 多种粒子作用
  • 3 代码

惯例声明:本人没有相关的工程应用经验,只是纯粹对相关算法感兴趣才写此博客。所以如果有错误,欢迎在评论区指正,不胜感激。本文主要关注于算法的实现,对于实际应用等问题本人没有任何经验,所以也不再涉及。

请添加图片描述

0 前言

Particle Life粒子生命演化最早是2017年由数字艺术家Jeffery Ventrella定义的,通过非常简单方法的定义粒子间的作用力,从而产生非常复杂的变化。

最开始Jeffery Ventrella管这种生成方法叫做Clusters,其思想来源于生物学家Lynn Margulus。每个粒子具有不同的颜色,每个颜色代表一种属性。粒子不仅会受到自己颜色粒子的吸引或排斥,也会受到其它颜色粒子的吸引和排斥。

在不同的参数下,粒子间会发生复杂的相互运动,某些参数会呈现出复杂的固定斑图,某些参数会呈现出类似生物之间的集群、逃跑、捕食等各种行为。

章节安排为:第一章主要是讲解原理,第二章演示一些基本的例子,第三章给出了基于MATLAB的具体代码。

本文的参考文献如下:
[1]粒子生命演化:由数量庞大的单体粒子演化出复杂的群体行为逻辑
https://www.bilibili.com/video/BV1Dh4y1t7hn/
https://www.youtube.com/watch?v=p4YirERTVF0
[2]https://particle-life.com
[3]blender3.6模拟-粒子生命-Particle Life
https://www.bilibili.com/video/BV1Ns4y1B7Fu/

1 基本原理

首先,假设一群粒子A,它们互相会受到其它粒子的作用力。两个粒子间的力大小是粒子间距离r的函数。

请添加图片描述

当距离r较小,小于rmin时,设置了-1的排斥力,为防止粒子之间重合。当粒子距离在rmin和rmax之间,粒子最大作用力为Fi。当粒子距离超过rmax,设置作用力为0,防止计算量过大。

当然有几个细节点需要注意:

1粒子所受的作用力只遵循上面的力方程,但不一定遵循牛顿第三定理。粒子的速度和加速度通过牛二律F=ma得到。由于防止粒子运动过快,还需要在全场设置粘滞阻尼。所以其实牛顿第一定理也不满足。当然由于这并不是精准的模拟仿真,所以这些小事可以忽略。

2力Fi是可以自行设置的,当Fi<0,粒子间呈现出排斥性,当Fi>0,粒子间呈现出吸引性,一般不超过±2;

3距离rmin通常在rmax的1/4~1/5左右;rmax和画布大小有关,rmax越大,越会有全局的粒子参与,rmax越小,粒子的行为越局部。

1.1 力影响-吸引排斥行为

当F<0时,粒子间呈现出排斥的现象:
请添加图片描述
当F>0时,粒子间呈现出吸引的现象:
请添加图片描述

1.2 距离rmax影响

这里画布大小都定义为1。
当rmax=0.2时,粒子的汇集效果如下:
请添加图片描述
当rmax=0.5时,粒子的汇集效果更全局化:
请添加图片描述

2 多种粒子相互作用

2.1 双种粒子作用

对于两种粒子A和B,力Fi共有4个,分别为A对A之间的力,A对B之间的力,B对A之间的力和B对B之间的力。这4个力可以写为一个矩阵形式:

AB
AF_AAF_AB
BF_BAF_BB

当假设A对A存在吸引,且A还会吸引B。但是B没有反向作用A的力,B与B之间也不会互相作用。这里的矩阵可以写作:
[ 1 0 0.5 0 ] \begin{bmatrix} 1 &0 \\ 0.5&0 \end{bmatrix} [10.500]
此时得到的图形为细胞图案,A粒子在中间互相吸引到一团,周围吸引一圈B粒子。
请添加图片描述
再添加两个规则给粒子B,粒子B之间会弱吸引,但粒子B排斥粒子A。此时由于粒子AB间一个吸引一个排斥,构成了不断向前运动的追逐系统。
[ 1 − 1 0.5 0.5 ] \begin{bmatrix} 1 &-1 \\ 0.5&0.5 \end{bmatrix} [10.510.5]
追逐模型如下:
请添加图片描述
之后多种粒子之间的运动规律,也是由上述各个规则叠加演化而成。
但是由于规则数量等于粒子种类N的平方,比如3种粒子就有9种粒子间规则,4种粒子就有16种粒子间规则。这就导致复杂性暴增,产生了无穷多的变化。

2.1 多种粒子作用

由于规则的复杂性,每一次随机出的结果可能都是独一无二的,且是其它人都未曾见过的。这种随机性和复杂性正是Particle Life的迷人之处。

下面列举一些演示计算结果
三种粒子,细胞图案:
请添加图片描述
三种粒子,岛屿图案:
请添加图片描述

三种粒子,循环捕食图案:
请添加图片描述
5种粒子的交互作用,呈现出一定的结构:
请添加图片描述

3 代码

上面绘图代码见文末。

主要更改粒子数量N,颜色数量NColor即可。建议粒子数量N大概是500倍颜色数量。不易太多,由于MATLAB运行效率较低,所以按照实际电脑配置自行更改。

力的作用距离Rmax在最好是1/c的形式,c是一个整数。

迭代总步数StepMax越大,展示的时间越长。这个如果想长时间欣赏粒子间作用,可以选择一个比较大的数。

图像刷新频率FrameFreq是用来控制多少个时间步显示一次。一般选择2就行,太大会有卡顿的感觉。

clear
clc
close all
%Particle Life粒子生命 MATLAB代码%% 初始设定参数
%初始设定
rng('shuffle');%随机种子
N=1500;%粒子数量
NColor=3;%颜色数量
Ni=rand(NColor,1);Ni=round(Ni*N/sum(Ni));%随机分配每个颜色对应的粒子数量
N=sum(Ni);Rmax=1/5;%力作用的距离
mcp=hsv(40);colormap(mcp(1:32,:));%定义展示颜色
StepMax=1.2e3;%结束迭代时间步
FrameFreq=2;%刷新率,正整数,最小为1,越大图像刷新越慢
%% 其它默认参数
%绘图范围
Xlim=[0,1];
Ylim=[0,1];
%定义每个粒子颜色编号
ColorP=zeros(N,1);
for t=1:NColorColorP(1+sum(Ni(1:t-1)):sum(Ni(1:t)))=t;
end
%粒子的力关系矩阵
FMat=rand(NColor,NColor)*3-1.5;%所有力Fi在-1.5~1.5之间
%粒子坐标速度
XY_P=rand(N,2)*0.8+0.1;%所有粒子点坐标
VXY_P=zeros(N,2);%粒子点速度Rmin=Rmax/5;%粒子间的最小作用距离
MeshMax=1/Rmax;%网格数量
dt=5e-3;%时间精度%构建力函数
t=0;%初始时间
c=Rmax*15.0*sqrt(N);%阻尼,为了防止粒子运动速度太快%% 循环计算每一步迭代
tJ=0;%绘图计数
for kt=1:StepMax%计算点对应的网格XYindx=ceil(XY_P/Rmax);%循环计算每个点所受的力ForceP=zeros(N,2);for kp=1:N %循环每一个点%该点的颜色、坐标和网格Color_k=ColorP(kp,:);XY_k=XY_P(kp,:);XYindx_k=XYindx(kp,:);%计算周围点对该点的力F_k=FMat(Color_k,ColorP)';[Indx_t,XY_P_B,F_B]=Beside9(XYindx_k,XYindx,MeshMax,XY_P,F_k);%周边点索引ForceP_k=F_Func(XY_P_B-XY_k,F_B,Rmin,Rmax);ForceP(kp,:)=ForceP_k;end%增加阻尼项,和v相反ForceP=ForceP-c.*VXY_P;%根据F更新位移x和速度v。dv=at,dx=vt+at^2/2VXY_P_New=VXY_P+ForceP*dt;XY_P=XY_P+0.5*(VXY_P+VXY_P_New)*dt;VXY_P=VXY_P_New;%循环边界条件,如果超出边界,就移到另一端XY_P(XY_P>1)=XY_P(XY_P>1)-1;XY_P(XY_P<0)=XY_P(XY_P<0)+1;t=t+dt;%加一时间步if ~mod(kt,FrameFreq)f=figure(1);f.Color=[1,1,1];cla;scatter(XY_P(:,1),XY_P(:,2),6,ColorP,"filled");xlim([0,1]);ylim([0,1]);%set(gca,'XTick',[],'YTick',[])axis offpause(0.01)%每一帧图像停留时间tJ=tJ+1;end
end%% 后置函数
function Ft2=F_Func(xy,F,rmin,rmax)
%粒子左右函数
%xy,N行2列的向量,代表别的点距离O点的距离向量
%F,N行1列的向量,代表吸引力F大小
rmid=0.5*(rmax+rmin);
dmid=0.5*(rmax-rmin);
r=sqrt(xy(:,1).^2+xy(:,2).^2);%距离
%r(r==0)=rmax;
Ft=zeros(size(r));
%第一段
indx1=(r<rmin);
Ft(indx1)=r(indx1)/rmin-1;
%第二段
indx_last=~indx1;
indx2=indx_last&(r<rmid);
Ft(indx2)=F(indx2).*(r(indx2)-rmin)/dmid;
%第三段
indx3=(r>=rmid)&(r<rmax);
Ft(indx3)=-F(indx3).*(r(indx3)-rmax)/dmid;
%计算力向量
dir_xy=xy./r;
dir_xy(isnan(dir_xy))=0;
Ft_Vec=dir_xy.*(Ft*ones(1,2));
%计算合力
Ft2=sum(Ft_Vec,1);
endfunction [BesideIndx1,XY_P_B,F_P]=Beside9(XYindx0,XYindx1,NMesh,XY_P,F_P)
%寻找点0附近区域3×3共9格区域内
%开启循环边界条件%复制出边界点,然后再计算。因为有的点在rmax较大的循环边界条件,会同时向上和下吸引
if XYindx0(1)==1%把最后一列复制一份到前面indx_t=XYindx1(:,1)==NMesh;XYindx1_t=XYindx1(indx_t,:);XYindx1_t(:,1)=0;%赋值为0XYindx1=[XYindx1;XYindx1_t];XY_P=[XY_P;XY_P(indx_t,:)+[-1,0]];F_P=[F_P;F_P(indx_t)];
end
if XYindx0(1)==NMesh%把第一列复制一份到最后indx_t=XYindx1(:,1)==1;XYindx1_t=XYindx1(indx_t,:);XYindx1_t(:,1)=NMesh+1;%赋值为NMesh+1XYindx1=[XYindx1;XYindx1_t];XY_P=[XY_P;XY_P(indx_t,:)+[1,0]];F_P=[F_P;F_P(indx_t)];
end
if XYindx0(2)==1%把最后一行复制一份到前面indx_t=XYindx1(:,2)==NMesh;XYindx1_t=XYindx1(indx_t,:);XYindx1_t(:,2)=0;%赋值为0XYindx1=[XYindx1;XYindx1_t];XY_P=[XY_P;XY_P(indx_t,:)+[0,-1]];F_P=[F_P;F_P(indx_t)];
end
if XYindx0(2)==NMesh%把第一行复制一份到最后indx_t=XYindx1(:,2)==1;XYindx1_t=XYindx1(indx_t,:);XYindx1_t(:,2)=NMesh+1;%赋值为NMesh+1XYindx1=[XYindx1;XYindx1_t];XY_P=[XY_P;XY_P(indx_t,:)+[0,1]];F_P=[F_P;F_P(indx_t)];
end
%夹在范围之内的点有哪些
BesideIndx_X=(XYindx0(1)-1<=XYindx1(:,1))&(XYindx1(:,1)<=XYindx0(1)+1);
BesideIndx_Y=(XYindx0(2)-1<=XYindx1(:,2))&(XYindx1(:,2)<=XYindx0(2)+1);
BesideIndx1=BesideIndx_X & BesideIndx_Y;
XY_P_B=XY_P(BesideIndx1,:);
F_P=F_P(BesideIndx1);
end

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/59209.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【已解决】Java 后端使用数组流 Array.stream() 将数组格式的 Cookie 转换成字符串格式

&#x1f389;工作中遇到这样一个场景&#xff1a;远程调用某个接口&#xff0c;该接口需要用户的 Cookie 信息进行权限认证&#xff0c;认证通过之后才可以打通并返回数据。 在后端拿到 httpServletRequest 后&#xff0c;调用 getCookies() 方法&#xff0c;返回的是一个 Coo…

WPF基础入门-Class6-WPF通知更改

WPF基础入门 Class6-WPF通知 1、显示页面&#xff1a; <Grid><StackPanel><TextBox Text"{Binding Name}"></TextBox><TextBox Text"{Binding Title}"></TextBox><Button Command"{Binding ShowCommand}&qu…

el-table动态生成多级表头的表格(js + ts)

展示形式&#xff1a; 详细代码&#xff1a; &#xff08;js&#xff09; <template><div><el-table :data"tableData" style"width: 100%"><el-table-column label"题目信息" align"center"><el-table-…

【C++】C++11的新特性(上)

引入 C11作为C标准的一个重要版本&#xff0c;引入了许多令人振奋的新特性&#xff0c;极大地丰富了这门编程语言的功能和表达能力。本章将为您介绍C11的一些主要变化和改进&#xff0c;为接下来的章节铺垫。 文章目录 引入 一、列表初始化 1、1 {} 初始化 1、2 std::initiali…

java 桥接模式

桥接模式 桥接模式简介桥接模式的实现总结 桥接模式简介 桥接模式&#xff08;Bridge&#xff09;是将抽象部分与它的实现部分分离&#xff0c;使它们都可以独立地变化。它是一种对象结构型模式&#xff0c;又称为柄体(Handle and Body)模式或接口(Interfce)模式。 桥接模式基于…

正则表达式 之 断言详解

正则表达式的先行断言和后行断言一共有 4 种形式&#xff1a; (?pattern) 零宽正向先行断言(zero-width positive lookahead assertion)(?!pattern) 零宽负向先行断言(zero-width negative lookahead assertion)(?<pattern) 零宽正向后行断言(zero-width positive lookb…

NEOVIM学习笔记

GitHub - blogercn/nvim-config: A pretty epic NeoVim setup 一直使用vim&#xff0c;每次到了新公司都要配置半天&#xff0c;而且常常配置失败&#xff0c;很多插件过期不好用。偶然看到别人的NEO VIM&#xff0c;就试着用了一下&#xff0c;感觉还不错。 用来开发和阅读C代…

Kubernetes(K8s)基本环境部署

此处只做学习使用&#xff0c;配置单master环境。 一、环境准备 1、ip主机规划&#xff08;准备五台新机&#xff09;>修改各个节点的主机名 注意&#xff1a;关闭防火墙与selinux 节点主机名ip身份joshua1 kubernetes-master.openlab.cn 192.168.134.151masterjoshua2k…

Python爬虫实战案例——第三例

文章中所有内容仅供学习交流使用&#xff0c;不用于其他任何目的&#xff01;严禁将文中内容用于任何商业与非法用途&#xff0c;由此产生的一切后果与作者无关。若有侵权&#xff0c;请联系删除。 起点中文网月票榜加密字体处理 字体加密的原理&#xff1a;就是将一种特定的…

11.Oracle中rollup函数详解

【基本介绍】 【格式】&#xff1a;group by rollup(字段1,字段2,字段3,...,字段n) 【说明】&#xff1a;rollup主要用于分组汇总&#xff0c;如果rollup中有n个字段&#xff0c;则会分别按【字段1】、【字段1,字段2】&#xff0c;【字段1,字段2,字段3】&#xff0c;...&#…

C++编辑修改PDF

PDFWriter是一个易于使用的C创建、修改PDF文档的库 1.创建一个PDF文件 #include #include “PDFWriter.h” int main() { std::cout << “Hello World!\n”; PDFWriter pdfWriter; int retpdfWriter.StartPDF(“D:\mytestwriterpdf.pdf”, ePDFVersion13); if (ret eS…

C++面向对象编程(2)

目录 一. 问题引入 二. 右值引用 1. lvalue/rvalue/prvalue/xvalue 1.1 表达式与对象的概念 1.2 左值与右值 2. moving semantics 2.1 显示绑定 2.2 Move constructors 2.3 Move assignment operator 2.4 实例分析 // TODO Quiz REF 本章简单介绍下move语义的“来…

day03_注释丶关键字丶标识符丶常量

​注释 注释就是使用人类的自然语言对代码的解释和说明。 代码本身和人类的自然语言相比&#xff0c;可读性肯定是要差一些&#xff0c;所以为了更快能够知道代码的含义、作用、需要注意地方&#xff0c;所有程序员都应该养成写注释的好习惯。 由于注释的内容是给程序员看的&…

《HelloGitHub》第 89 期

兴趣是最好的老师&#xff0c;HelloGitHub 让你对编程感兴趣&#xff01; 简介 HelloGitHub 分享 GitHub 上有趣、入门级的开源项目。 https://github.com/521xueweihan/HelloGitHub 这里有实战项目、入门教程、黑科技、开源书籍、大厂开源项目等&#xff0c;涵盖多种编程语言 …

融合正余弦和柯西变异的麻雀搜索算法(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

Error running ‘Tomcat 8.5.29‘ Address localhost:1099 is already in use

一、Error running ‘Tomcat 8.5.29’ Address localhost:1099 is already in use 原因&#xff1a;端口1099被占用了。 二、解决 2.1 解决方法一-结束该端口1099占用 //1-查看端口占用&#xff0c;根据端口号1099&#xff0c;获取PID(进程ID) netstat -ano | findstr "…

stackoverflow问题

Stack Overflow requires external JavaScript from another domain, which is blocked or failed to load. stackoverflow引用了谷歌中被屏ajax.googleapis.com的jquery.min.js文件。“https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js” 方案1.打开网站…

字节一面:你能讲一下跨域吗

前言 最近博主在字节面试中遇到这样一个面试题&#xff0c;这个问题也是前端面试的高频问题&#xff0c;作为一名前端开发工程师&#xff0c;我们日常开发中与后端联调时一定会遇到跨域的问题&#xff0c;只有处理好了跨域才能够与后端交互完成需求&#xff0c;所以深入学习跨域…

docker 04.更加重要的命令

之前的都是基础命令&#xff0c; 前台交互进程和后台守护进程&#xff1a; 重新进入容器&#xff1a; docker中的导入导出&#xff1a; docker中的拷贝到&#xff1a;

ubuntu学习(五)----读取文件以及光标的移动

1、读取文件函数原型介绍 ssize_t read(int fd,void*buf,size_t count) 参数说明&#xff1a; fd: 是文件描述符 buf:为读出数据的缓冲区&#xff1b; count: 为每次读取的字节数&#xff08;是请求读取的字节数&#xff0c;读上来的数据保存在缓冲区buf中&#xff0c;同时文…