1.背景
集群智能作为一种模拟自然界中的群体行为和协作方式来解决问题的智能系统方法,在包括优化问题、数据挖掘、交通规划、无人机协同操作、分布式传感器网络等领域都有应用的价值与潜力。
而作为实现集群智能的一种建模方法,Agent-Based Modeling(ABM,代理基础建模)通过构建具体的模型以模拟个体代理及其组成的群体之间的互动,进而研究整体系统的行为与演化。在建筑设计中具有通过模拟人、车流以辅助空间设计决策的价值潜力。
2.模拟程序构建
本项目以经典风格化的建筑平面为灵感,期望通过控制点及其群体间的运动关系形成具有一定风格特征的轨迹图形。结合ABM的相关技术路径,项目的整体目标为模拟一组代理个体之间的运动和互动,包括避免碰撞、保持群体凝聚性等行为。代理的运动路径通过线条表示,可以用来观察代理的行为。此外,代理还有一些控制参数,如最大速度、最大施加力等,以调整其行为。
2.1 代理对象创建
通过定义Agent类以模拟个体代理点的位置、移动速度和加速度信息,并通过一系列函数方法模拟控制代理点的行为,如移动、碰撞、转折、活动范围控制等。
class Agent{
PVector loc;
PVector vel=new PVector(random(-1,1)*4.0,random(-1,1)*2.0);
PVector acc=new PVector(0,0);
float r=10;
float maxspeed=6;
float maxforce=0.05;
PVector v0=new PVector(1,1);
PVector vlast;
PVector loc0=new PVector(0,0);//临时loc
PVector loclast=new PVector(0,0);//上一个位置
ArrayList<PVector> locs=new ArrayList<PVector>();
boolean dead=false;
int id;
int turns=0;//转折次数
int grid=10;
int lineWeight=1;
Agent(PVector _loc,int idnumber){
loc=_loc;
id=idnumber;
}
void run(){ //主要的代理运行方法,包括移动、计算转折次数、检查边缘和保存位置
//display();
move(); //计算代理的移动,包括速度和位置的更新
calTurns();//计算调整方向次数
//checkEdge(); //检查代理是否越过了画布的边界
saveLoc(); //保存代理的位置到 locs 列表中
}
void display(){
//ellipse(loc0.x,loc0.y,1,1);
if(v0.x==0)lineWeight=1;
if(v0.y==0)lineWeight=2;
strokeWeight(lineWeight);
line(loc0.x,loc0.y,loclast.x,loclast.y);
}
void move(){
vel.add(acc);
vel.limit(maxspeed);
vlast=new PVector(v0.x,v0.y);
if(abs(vel.x)>=abs(vel.y)) v0=new PVector(vel.x,0);
if(abs(vel.x)<abs(vel.y)) v0=new PVector(0,vel.y);
loc.add(v0);
//loc.add(vel);
loclast.x=loc0.x;
loclast.y=loc0.y;
//模数化
if(v0.x==0){
if(loc.x%grid<grid/2){
loc0.x=loc.x-loc.x%grid;
}else{
loc0.x=loc.x-loc.x%grid+grid;
}
loc0.y=loc.y;
}
if(v0.y==0){
if(loc.y%grid<grid/2){
loc0.y=loc.y-loc.y%grid;
}else{
loc0.y=loc.y-loc.y%grid+grid;
}
loc0.x=loc.x;
}
acc.set(0,0);
}
void saveLoc(){
locs.add(new PVector(loc.x,loc.y));
}
void calTurns(){
if(v0.dot(vlast)<=0){
turns++;
//lineWeight=turns%2+1;
//转角处的点修改位置保证直角
if(v0.x==0)loc0.y=loclast.y;
if(v0.y==0)loc0.x=loclast.x;
}
}
void checkEdge(){
if(loc.x<0)
{loc.x=0;vel.mult(-1);}
if(loc.x>width)
{loc.x=width;vel.mult(-1);}
if (loc.y<0)
{loc.y=0;vel.mult(-1);}
if(loc.y>height)
{loc.y=height;vel.mult(-1);}
}
//后接2.2中代码块
2.2 群体行为
主要考虑分离(separate())和凝聚(cohesion())两种群体关系,通过个体点之间的运动关系一定程度上限制了线条的距离疏密,形成在构成关系上符合应用需求的图形。
//接上节代码块
void flock(){
separate();
cohesion();
}
void separate(){
PVector steer=new PVector(0,0);
int count =0;
for (Agent another:agents){
float dis=loc.dist(another.loc);
if(dis>0&&dis<30){
PVector diff=PVector.sub(loc,another.loc);
diff.normalize();
diff.div(dis);
steer.add(diff);
count++;
}
}
if(count>0){
steer.setMag(maxspeed);
steer.sub(vel);
steer.limit(maxforce);
steer.mult(1.5);
acc.add(steer);
}
}
void cohesion(){
PVector steer=new PVector(0,0);
int count =0;
for (Agent another:agents){
float dis=loc.dist(another.loc);
if(dis>0&&dis>60){
steer.add(another.loc);
count++;
}
}
if(count>0){
steer.div(count);
steer.sub(loc);
steer.setMag(maxspeed);
steer.sub(vel);
steer.limit(maxforce);
//steer.mult(0.2);
//steer.x=steer.x*2.0;
acc.add(steer);
}
}
}
3. 初始化环境及运行结果
3.1 初始化环境
实际运行需要先行设置程序的初始环境(背景大小、颜色等)及一系列初始化操作,我们通过循环初始化一定数量的个体代理点的位置及标识符并运行相应的模拟程序,进而实现相应情境的集群模拟。
ArrayList<Agent> agents=new ArrayList<Agent>();
int flag=1;
int times=0;//记录循环次数
void setup(){
size(800,800);
background(255);
for (int i=0;i<10;i++){
agents.add(new Agent(new PVector(random(width/80)+width/2,random(height/80)+height/2),i));
//agents.add(new Agent(new PVector(random(width/8)+width/4,random(height/8)+height/4),i));
}
for (int i=0;i<10;i++){
agents.add(new Agent(new PVector(random(width/80)+width/2,random(height/80)+height/2+20),i+10));
//agents.add(new Agent(new PVector(random(width/8)+width/4,random(height/8)+height/4),i));
}
}
void draw(){
times++;
fill(0);
for(Agent agent:agents){
if (!agent.dead){
if(times>30){
checkDead(agent);
}
agent.run();
if(times>2){
agent.display();
}
agent.flock();
}
}
}
void checkDead(Agent agent){
//如果速度小于一定值,就死亡
if(agent.v0.mag()<0.2)agent.dead=true;
//如果碰到别的墙,就死亡
for(Agent another:agents){
if (another.id!=agent.id){
for(PVector loc:another.locs){
float dist=agent.loc.dist(loc);
if(dist<6.0){agent.dead=true;}
}
}
}
//如果转向超过4次,死亡
if(agent.turns>6)agent.dead=true;
}
void mousePressed() {
//saveFrame("pic_####.jpg");
if(flag==1){
flag=0;
noLoop();
}else{
flag=1;
loop();
}
}
3.2 运行结果
最终运行的结果在图面上具有随机而丰富的表达效果,并且在改写接入rhino-gh平台后有往三维模型方向生成的潜力,目前成果上看创作的交互趣味性更强,实用性有待提高。