在processing里使用80行代码制作一个元胞自动机之癌细胞扩散模型
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了在processing里使用80行代码制作一个元胞自动机之癌细胞扩散模型相关的知识,希望对你有一定的参考价值。
今天研究了一下元胞自动机,在学习之前,总觉得这个名词很陌生,今天我们就来把这张纸捅破,看看到底什么是"元胞自动机"
下面是百度百科的结果:
元胞自动机(cellular automata,CA)
是一种时间、空间、状态都离散,空间相互作用和时间因果关系为局部的网格动力学模型,具有模拟复杂系统时空演化过程的能力。
通俗来说,元胞自动机就是一个盒子,这个盒子里有很多"细胞",每个"细胞"可以有自己的状态,与此同时,这些"细胞"的运动是随机的且受周围"细胞"的影响。
下面是元胞自动机的特征,了解这些特征后,你会对它有更深的认识:
- 同步计算(并行性):元胞自动机的处理是同步进行的
- 同质性:元胞空间内的每个元胞都服从相同的规则
- 时空局域性:
每个元胞在t+1时刻的状态,取决于其邻居的元胞在t时刻的状态;
t时刻的状态只对t+1时刻的状态产生影响
今天要做的模型是癌细胞的扩散模型,在写代码前,我们先来分析一下这个模型的具体内容:
- 制定元胞自动机的基本规则
- 从一个癌细胞开始,探究感染率与时间的关系
制定元胞自动机的基本规则
我们今天从最简单的癌细胞扩散模型开始
首先,我们先定义一个400400的空间,里面有400400个细胞,在生物学中,我们知道癌细胞是突变的细胞,在模型中,我们把时间点拖到产生癌细胞那一刻,因此,程序开始时,会随机从400*400个细胞中选择一个正常细胞,并把它变成癌细胞。这是整个程序刚开始的思路,我们来看一下细节:
int[][] beds = new int[400][400];
int x_limit = 400;
int y_limit = 400;
这里是定义空间大小,我们用一个二维数组表示,beds[0][0]表示第一行第一列的细胞,可以想象成一个沿X轴对称的二维坐标轴
color red = color(255, 0, 0); // red
color white = color(255, 255, 255); // white
int Healthy = 0;
int Infected = 1;
这里我们定义正常细胞为0,癌细胞为1:
若beds[0][0] = 0,则表示第一行第一列的细胞为正常的细胞,并标识为白色;
若beds[0][0] = 1,则表示第一行第一列的细胞为癌细胞,并标识为红色
int count = 0;
float tau = 0.5;
count用来统计时间点;tau表示癌变的概率。
boolean prob( float p )
if (random(0, 1) < p) return true;
else return false;
这里我们自定义一个函数,在0和1之间随机生成一个浮点数,若该数小于癌变的概率,则让该细胞感染,具体调用方法如下,我们在后面会用到:
if (prob(tau)) cell = 1;
下面我们在processing编辑器里编写setup初始化函数:
void setup()
size(400, 400);
frameRate(50);
for (int x = 0 ; x < x_limit ; x++)
for (int y = 0 ; y < y_limit ; y++)
beds[x][y] = Healthy;
//println("beds[" + x + "][" + y + "]:" + beds[x][y]);
stroke( white );
int lucky_x = int(random(0, 400));
int lucky_y = int(random(0, 400));
beds[lucky_x][lucky_y] = 1;
//println("beds[" + lucky_x + "][" + lucky_y + "]:" + beds[lucky_x][lucky_y]);
那两个println语句大家可以在自己敲的时候补上,看看它的初始化过程,第二个println语句展示了是哪个细胞癌变了
从一个癌细胞开始探究感染率与时间的关系
下面开始制定癌细胞的感染规则,假设一个正常细胞的位置是(X,Y),那么它周围的细胞里,如果有癌细胞的话,那么它自己就有被感染的风险,在上面我们也讲过了,这个风险值为0.5,我们来看看怎么表示细胞(X,Y)周围的细胞:
用代码可以这样表示:
if (cell == Healthy)
if (beds[x][y-1]==1 || beds[x][y+1]==1 || beds[x-1][y]==1 || beds[x+1][y]==1 || beds[x-1][y+1]==1 || beds[x+1][y+1]==1 || beds[x+1][y-1]==1 || beds[x-1][y-1]==1)
if (prob(tau))
cell = 1;
如果一个细胞是正常的细胞,那就去判断它周围的8个细胞,只要这8个细胞里有一个癌细胞,那么它就有被感染为癌细胞的可能,把风险带入prob函数计算,如果条件符合,则这个正常细胞变成癌细胞
变成癌细胞以后,我们还需要用颜色直观的表示出来,为了并行性,我们把感染过程和绘图分成两个函数,在绘图函数中调用感染过程的函数:
void draw()
update();
int sum = 0;
for (int x = 0 ; x < x_limit ; x++)
for (int y = 0 ; y < y_limit ; y++)
//println("beds[" + x + "][" + y + "]:" + beds[x][y]);
if (beds[x][y] == Infected)
sum++;
stroke( red );
else
stroke( white );
point( x, y );
println("Time:"+count);
println("Sum:"+sum);
println("--------------------");
count++;
//toDraw = (toDraw == 0) ? 1 : 0;
void update()
int x, y, cell;
//int toCompute = (toDraw == 0) ? 1 : 0;
for (x = 1 ; x < x_limit-1 ; x++)
for (y = 1 ; y < y_limit-1 ; y++)
cell = beds[x][y];
if (cell == Healthy)
if (beds[x][y-1]==1 || beds[x][y+1]==1 || beds[x-1][y]==1 || beds[x+1][y]==1 || beds[x-1][y+1]==1 || beds[x+1][y+1]==1 || beds[x+1][y-1]==1 || beds[x-1][y-1]==1)
if (prob(tau))
cell = 1;
beds[x][y] = cell;
核心思想就是上面讲的那些,其他代码主要是遍历每个细胞的过程,因为是二维数组,因此这里用两个for循环,想做成三维的话,就放三个for循环。
下面来看一下效果:
前两个时间点
第五个时间点
第二十六个时间点
第五十二个时间点
可以看到,癌细胞在不断扩散,并且速度越来越快 第九十个时间点
第一百二十五个时间点
第一百六十六个时间点
现在有144862个细胞被感染成癌细胞,再往下看 第二百六十六个时间点
癌细胞大获全胜
声明:
- 这里的时间节点指一个正常细胞被完全感染的时间
- 该模型是比较简单的版本,实际情况中,还要考虑其他问题
以上就是全部内容,如有疑问,欢迎大家在下方评论区留言!
Qt获取命令行的执行结果|在标签上显示图片
分享两种获取CMd命令行执行结果的方法
//写在源代码部分
QProcess process;
//执行开始,括号里的字符串是执行的命令
process.start("tasklist");
//设置命令执行过后,多少时间后来获取执行结果,单位毫秒
process.waitForFinished(2000);
QByteArray output = process.readAllStandardOutput();
//声明字符串用来接收执行的结果
QString stroutput = output;
//将执行结果赋值给label标签,这样就可以用label来显示命令执行结果
ui->label->setText(stroutput);
//关闭执行
process.close();
//写在源代码部分
QProcess process;
//执行输入行内的内容
process.start("cmd", QStringList()<<"/c"<<ui->lineEdit->text());
//设置命令执行过后,多少时间后来获取执行结果,单位毫秒
process.waitForFinished(200);
QByteArray output = process.readAllStandardOutput();
QString stroutput = QString::fromLocal8Bit(output);
//将执行的命令赋值给文本框
ui->textEdit->append(stroutput);
//关闭执行
process.close();
获取命令的示例
//写在源代码部分
//引入头文件 #include <QMovie>
QMovie *movie = new QMovie(":/new/img/23.gif");
movie->start();
ui->label->setMovie(movie);
//原理是在label上新建一个标签用来播放图片
在标签上显示图片示例
//图片弹框源码
#include "imgshow.h"
#include "ui_imgshow.h"
#include <QMovie>
imgShow::imgShow(QWidget *parent) :
QDialog(parent),
ui(new Ui::imgShow)
{
ui->setupUi(this);
QMovie *movie = new QMovie(":/new/img/23.gif");
ui->label->setMovie(movie);
movie->start();
}
imgShow::~imgShow()
{
delete ui;
}
以上是关于在processing里使用80行代码制作一个元胞自动机之癌细胞扩散模型的主要内容,如果未能解决你的问题,请参考以下文章