基于斥力-张力模型的网络拓扑布局算法(php代码)

根据之前的C++代码改写:

<?php
	//**********************************************************//
	//date:2014.11.07 @ bupt
	//本PHP文件包括顶点类Point、图类Graph、以及相关函数
	//Graph对象的构造函数的输入为(顶点个数:$_Nv,x轴最小值:$_xmin,x轴最大值:$_xmax,y轴最小值:$_ymin,y轴最大值:$_ymax,邻接矩阵$_mat)
	//Graph对象的initLayoutProc()方法是初始化布局过程
	//Graph对象的layOut()方法是进行一次布局
	//当Graph对象的成员变量温度T小于1时,停止布局,根据画布大小进行平移和缩放
	//**********************************************************//
	//
	//示例程序如下:
	//$tNv = 4;//顶点的个数
	//$txmin = 0;//x轴最小值
	//$txmax = 400;//x轴最大值
	//$tymin = 0;//y轴最小值
	//$tymax = 400;//y轴最大值
	//
	////邻接矩阵
	//$tmat = array(
	//	0=>array(0,1,1,0),
	//	1=>array(1,0,1,1),
	//	2=>array(1,1,0,1),
	//	3=>array(0,1,1,0)
	//	);
	//
	//
	//$g = new Graph($tNv,$txmin,$txmax,$tymin,$tymax,$tmat);//初始化拓扑图
	//$g->initLayoutProc();//初始化布局过程
	//$g->outPut();//输出图
	//while ($g->T >= 1) {
	//	//$g->layOut();//进行一次布局
	//}
	//$g->layOut();//$this->T<1时,此时布局部已完成,进行平移和缩放
	//$g->outPut();//
	//**********************************************************//
	//
	//
	//
	//需要用到的函数
	function init3($v,$x,$y){//初始化
		$v[0]=$x;
		$v[1]=$y;
		return $v;
	}
	function len3($v){//计算模
		$len=sqrt($v[0]*$v[0]+$v[1]*$v[1]);
		if($len==0)$len=0.001;
		return $len;
	}
	function len3_2($v){//计算平方和
		return $v[0]*$v[0]+$v[1]*$v[1];
	}
	function sub3($a,$b,$rs){//计算向量的差
		$rs[0]=$a[0]-$b[0];
		$rs[1]=$a[1]-$b[1];
		return $rs;
	}
	function add3($a,$b,$rs){//计算向量的和
		$rs[0]=$a[0]+$b[0];
		$rs[1]=$a[1]+$b[1];
		return $rs;
	}
	function mul3($k,$v,$rs){//计算向量与常数的乘积
		$rs[0]=$k*$v[0];
		$rs[1]=$k*$v[1];
		return $rs;
	}
	function fa($d,$K){//引力位移
		return $d*$d/$K;
	}
	function fr($d,$K){//斥力位移
		return $K*$K/$d;
	}
	////////////////////////////////////////////////

	//顶点类
	class Point
	{
		var $pos;//点的位置
		var $offset;//点的位移
		var $weight;//点的重量
		var $degree;//点的度数
		var $force;//合力

		function __construct()//构造函数
		{
			$this->pos = array(0,0);
			$this->offset = array(0,0);
			$this->weight=0;
			$this->degree=0;
			$this->force=array(0,0);
		}

	}

	//图类
	class Graph
	{

		var $Nv;//顶点的个数
		var $xmin;//x轴最小值
		var $xmax;//x轴最大值
		var $ymin;//y轴最小值
		var $ymax;//y轴最大值
		var $mat;//邻接矩阵vector<vector<bool> > mat;
		var $vlist;//顶点列表vector<Cvertex> vlist;

		//引力-斥力模型
		var $K;//引力常数
		var $T;//当前温度
		var $Jf;//前一次的目标函数值
		var $decay;//衰减常数

		function __construct($_Nv,$_xmin,$_xmax,$_ymin,$_ymax,$_mat)//复杂构造函数
		{
			$this->Nv=$_Nv;
			$this->xmin=$_xmin;
			$this->xmax=$_xmax;
			$this->ymin=$_ymin;
			$this->ymax=$_ymax;
			$this->mat=$_mat;
			$this->decay=0.85;

			for($i=0;$i<$_Nv;$i++){
				$this->vlist[$i]=new Point();
				$this->vlist[$i]->pos[0] = rand($this->xmin,$this->xmax);
				$this->vlist[$i]->pos[1] = rand($this->ymin,$this->ymax);

			}

		}

		function shutLayoutProc(){//关闭布局过程
			$this->T=0;
		}

		function initLayoutProc(){//初始化布局过程
		//初始化引力常数
			$INF=100000000;
			$area=($this->xmax-$this->xmin)*($this->ymax-$this->ymin);
			$this->K=pow($area/$this->Nv,0.5);
			//初始化温度
			$this->T=($this->xmax-$this->xmin);
			//初始化目标函数值
			$this->Jf=$INF;
			//初始化衰减系数
			$decay=0.9;
		}

		function layOut(){//进行一次布局
			$INF=100000000;
			if($this->T<=1){	//T为当前温度
				//此时布局部已完成,进行平移和缩放
				//求外接矩形
					$left=$INF;
					$right=-$INF;
					$up=-$INF;
					$down=$INF;
					for($i=0;$i<=$this->Nv-1;$i++){
						if($this->vlist[$i]->pos[0]<$left)$left=$this->vlist[$i]->pos[0];
						if($this->vlist[$i]->pos[0]>$right)$right=$this->vlist[$i]->pos[0];
						if($this->vlist[$i]->pos[1]>$up)$up=$this->vlist[$i]->pos[1];
						if($this->vlist[$i]->pos[1]<$down)$down=$this->vlist[$i]->pos[1];
					}//得到left,right,up,down

					echo "</br>left:".$left.",right:".$right.",up:".$up.",down:".$down."</br></br>";

					//求外接矩形中心
					$_cx=($left+$right)/2;
					$_cy=($up+$down)/2;
					//求画板中心
					$cx=($this->xmin+$this->xmax)/2;
					$cy=($this->ymin+$this->ymax)/2;
					//由外接矩形中心向画板中心的平移向量
					$vec = array($cx-$_cx,$cy-$_cy);
					//按平移向量对图形进行平移,但只移若干分之一,而不一步到位,为的是动画效果
					for($i=0;$i<=$this->Nv-1;$i++){
						$this->vlist[$i]->pos[0]+=$vec[0];
						$this->vlist[$i]->pos[1]+=$vec[1];
					}
					//求外接矩形的最大边心距
					$r=max(($this->xmax-$this->xmin)/2,($this->ymax-$this->ymin)/2);
					//求边心距的最大可增加量
					$dr=min(($this->xmax-$this->xmin)/2-($right-$left)/2,($this->ymax-$this->ymin)/2-($up-$down)/2);
					$dr=$dr-($this->xmax-$this->xmin)/15;//防止顶天
					//$_dr=$dr/1000;//只取最大可增加量的若干分之一,为的是动画效果
					//求缩放系数
					$k=($r+$dr)/$r;
					//按k对图形进行缩放,
					for($i=0;$i<=$this->Nv-1;$i++){
						$this->vlist[$i]->pos[0]=($this->vlist[$i]->pos[0]-$_cx)*$k+$_cx;
						$this->vlist[$i]->pos[1]=($this->vlist[$i]->pos[1]-$_cy)*$k+$_cy;
					}
				return;
			}
			//将各顶点的offset恢复为0
			for($i=0;$i<=$this->Nv-1;$i++){
				$this->vlist[$i]->offset = init3($this->vlist[$i]->offset,0,0);
			}
			//在斥力作用下位移
			for($i=0;$i<=$this->Nv-1;$i++){
				for($j=0;$j<$i;$j++){
					//计算位移向量offset和_offset
					$diff=array(0,0);

					/*
					echo "i:".$i.",j:".$j;

					echo "</br>vlist_i_pos:";
					echo $this->vlist[$i]->pos[0];
					echo ",";
					echo $this->vlist[$i]->pos[1];
					echo "</br>";

					echo "</br>vlist_j_pos:";
					echo $this->vlist[$j]->pos[0];
					echo ",";
					echo $this->vlist[$j]->pos[1];
					echo "</br>";//*/

					$diff = sub3($this->vlist[$i]->pos,$this->vlist[$j]->pos,$diff);
					$len_diff = len3($diff);//|diff|

					/*
					echo "</br>diff:";
					echo $diff[0];
					echo ",";
					echo $diff[1];
					echo "</br>";

					echo "</br>len_diff:";
					echo $len_diff;
					echo "</br>";//*/

					$e_diff = array(0,0);//diff/|diff|
					$e_diff = mul3(1.0/$len_diff,$diff,$e_diff);
					$offset = array(0,0);//(diff/|diff|)*fr(|diff|)
					$offset = mul3(fr($len_diff,$this->K),$e_diff,$offset);
					$_offset = array(0,0);//-offset
					$_offset = mul3(-1,$offset,$_offset);
					//累计位移量
					$this->vlist[$i]->offset = add3($this->vlist[$i]->offset,$offset,$this->vlist[$i]->offset);
					$this->vlist[$j]->offset = add3($this->vlist[$j]->offset,$_offset,$this->vlist[$j]->offset);
				}
			}
			//在引力作用下位移
			for($i=0;$i<=$this->Nv-1;$i++){
				for($j=0;$j<$i;$j++){
					if($this->mat[$i][$j]){
						//计算位移向量offset和_offset
						$diff=array(0,0);
						$diff=sub3($this->vlist[$i]->pos,$this->vlist[$j]->pos,$diff);
						$len_diff=len3($diff);//|diff|
						$e_diff=array(0,0);//diff/|diff|
						$e_diff=mul3(1.0/$len_diff,$diff,$e_diff);
						$offset=array(0,0);//(diff/|diff|)*fr(|diff|)
						$offset=mul3(fa($len_diff,$this->K),$e_diff,$offset);
						$_offset=array(0,0);//-offset
						$_offset=mul3(-1,$offset,$_offset);
						//累计位移量
						$this->vlist[$i]->offset=add3($this->vlist[$i]->offset,$_offset,$this->vlist[$i]->offset);
						$this->vlist[$j]->offset=add3($this->vlist[$j]->offset,$offset,$this->vlist[$j]->offset);
					}
				}
			}
			//进行位移(限制移动距离不超过T)
			for($i=0;$i<=$this->Nv-1;$i++){
				$len_offset=array(0,0);

				/*
				echo "</br>vlist_offset";
				echo $this->vlist[$i]->offset[0];
				echo ",";
				echo $this->vlist[$i]->offset[1];
				echo "</br>";//*/

				$len_offset=len3($this->vlist[$i]->offset);//位移量的模
				$e_offset=array(0,0);//位移量的方向
				$e_offset=mul3(1.0/$len_offset,$this->vlist[$i]->offset,$e_offset);//得到e_offset
				$len_offset=min($len_offset,$this->T);//得到len_offset
				$offset=array(0,0);//位移量
				$offset=mul3($len_offset,$e_offset,$offset);//得到offset
				/*
				echo "</br>len_offset:";
				echo $len_offset;
				echo "</br>";

				echo "</br>e_offset:";
				echo $e_offset[0];
				echo ",";
				echo $e_offset[1];
				echo "</br>";

				echo "</br>offset:";
				echo $offset[0];
				echo ",";
				echo $offset[1];
				echo "</br>";//*/
				$this->vlist[$i]->pos=add3($this->vlist[$i]->pos,$offset,$this->vlist[$i]->pos);
			}
			//降温
	    	$this->T=$this->decay*$this->T;
		}

		function outPut(){
			echo "Point Number:".$this->Nv;
			echo "</br>";
			echo "</br>";
			echo "Adjacent Matrix:";
			echo "</br>";
			for($i=0;$i<$this->Nv;$i++){
				for($j=0;$j<$this->Nv;$j++){
					echo $this->mat[$i][$j];
					echo " ";
				}
				echo "</br>";
			}
			echo "</br>";

			echo "x:".$this->xmin.",".$this->xmax;
			echo "</br>";
			echo "y:".$this->ymin.",".$this->ymax;
			echo "</br>";
			echo "</br>";

			echo "Repulsive Const:".$this->K;
			echo "</br>";
			echo "Now Temperature:".$this->T;
			echo "</br>";
			echo "Prev Function Value:".$this->Jf;
			echo "</br>";
			echo "Attenuation Const:".$this->decay;
			echo "</br>";

			echo "</br>";
			echo "Point Pos:";
			echo "</br>";
			for($i=0;$i<$this->Nv;$i++){
				echo $i;
				echo ":";
				echo $this->vlist[$i]->pos[0];
				echo ",";
				echo $this->vlist[$i]->pos[1];
				echo "</br>";
			}

		}

	}

	//echo $INF;
	$tNv = 4;//顶点的个数
	$txmin = 0;//x轴最小值
	$txmax = 400;//x轴最大值
	$tymin = 0;//y轴最小值
	$tymax = 400;//y轴最大值

	//邻接矩阵
	$tmat = array(
		0=>array(0,1,1,0),
		1=>array(1,0,1,1),
		2=>array(1,1,0,1),
		3=>array(0,1,1,0)
		);

	$g = new Graph($tNv,$txmin,$txmax,$tymin,$tymax,$tmat);//初始化拓扑图
	$g->initLayoutProc();//初始化布局过程
	$g->outPut();//输出图
	while ($g->T >= 1) {
		$g->layOut();//进行一次布局
	}
	$g->outPut();//
	$g->layOut();//$this->T<1时,此时布局部已完成,进行平移和缩放
	$g->outPut();//
?>
时间: 2024-10-12 20:15:38

基于斥力-张力模型的网络拓扑布局算法(php代码)的相关文章

基于斥力-张力模型的网络拓扑布局算法

详细内容见http://user.qzone.qq.com/350479720/blog/1306948704 代码见http://www.oschina.net/code/snippet_149334_4576 OpenGL配置见http://www.cnblogs.com/phinecos/archive/2007/07/28/834668.html

基于能量水平的无线传感器网络拓扑控制研究

基于能量水平的无线传感器网络拓扑控制研究 摘要:在无线传感器网络的规划和设计中,减少节点的能量消耗.延长其工作时间并最大化网络的生命周期是首先要解决的重要问题.本文设计了一种基于节点能量水平的拓扑控制策略,该策略针对汇聚节点附近节点的能量消耗过多而设计,避免了这些节点因能量过早耗尽而导致的网络失效,该机制使网络中的节点能量消耗更加均衡,延长了网络的寿命.最后通过程序仿真验证了该方法的有效性. 关键词:无线传感器网络,能量水平,网络拓扑 一. 提出问题     最小能量消耗路由是从数据源到汇聚节点

基于Spark MLlib平台的协同过滤算法---电影推荐系统

基于Spark MLlib平台的协同过滤算法---电影推荐系统 又好一阵子没有写文章了,阿弥陀佛...最近项目中要做理财推荐,所以,回过头来回顾一下协同过滤算法在推荐系统中的应用. 说到推荐系统,大家可能立马会想到协同过滤算法.本文基于Spark MLlib平台实现一个向用户推荐电影的简单应用.其中,主要包括三部分内容: 协同过滤算法概述 基于模型的协同过滤应用---电影推荐 实时推荐架构分析     一.协同过滤算法概述 本人对算法的研究,目前还不是很深入,这里简单的介绍下其工作原理. 通常,

车道线检测文献解读系列(一) 基于机器视觉的高速车道标志线检测算法的研究_李晗

作者背景 基于机器视觉的高速车道标志线检测算法的研究_李晗 东北大学车辆工程硕士学位论文 2006年 [GB/T 7714]李晗. 基于机器视觉的高速车道标志线检测算法的研究[D]. 东北大学, 2006. DOI:10.7666/d.y852642.` 论文结构一览 预处理 灰度化 [亮点]模式判别 选择日间模式还是夜间模式: 在每个检测周期开始时,首先判断采用日间模式还是夜间模式工作.摄像机视野中的上半部分为天空背景,天空亮度可以显著区分日间和夜间环境.由于天空的颜色为蓝离,日间天空的蓝色分

CSS3弹性盒模型,Flex布局教程

布局的传统解决方案,基于盒状模型,依赖 display属性 + position属性 + float属性.它对于那些特殊布局非常不方便,比如,垂直居中就不容易实现. CSS3中引入flex的弹性盒模型,这是一个可以让你告别浮动.完美实现垂直水平居中的新特性. 尽管目前css3在PC端上的兼容性还不是那么完美,但是在移动端已基本实现兼容. 网络上有很多关于flex布局很好的教程.总结的也很完美,我就直接收藏了,以备查询 详解css3弹性盒模型(Flexbox) 移动端开发小记 – Flexbox

基于朴素贝叶斯分类器的文本分类算法

源代码下载:NaviveBayesClassify.rar Preface 文本的分类和聚类是一个比较有意思的话题,我以前也写过一篇blog<基于K-Means的文本聚类算法>,加上最近读了几本数据挖掘和机器学习的书籍,因此很想写点东西来记录下学习的所得. 在本文的上半部分<基于朴素贝叶斯分类器的文本分类算法(上)>一文中简单介绍了贝叶斯学习的基本理论,这一篇将展示如何将该理论运用到中文文本分类中来,具体的文本分类原理就不再介绍了,在上半部分有,也可以参见代码的注释. 文本特征向量

弹性盒模型(伸缩布局)

一.弹性盒模型(伸缩布局) flxible box 前言: 弹性布局,用来为盒子提供灵活性.就像是当把浏览器缩小的的时候,不会像float属性会依然往下掉,灵活性不好.而且当布局盒装模型的时候依赖于float+position+display,例如实现垂直居中就很不方便了. 一)语法 {display: flex;} /*作为块级伸缩盒子显示*/ {display: inline-flex;} /*作为内联块级伸缩盒子显示:行内的元素也能使用*/ 是不是感觉很熟悉呢?这就类似于 block 和 

美团网基于机器学习方法的POI品类推荐算法

美团网基于机器学习方法的POI品类推荐算法 前言 在美团商家数据中心(MDC),有超过100w的已校准审核的POI数据(我们一般将商家标示为POI,POI基础信息包括:门店名称.品类.电话.地址.坐标等).如何使用这些已校准的POI数据,挖掘出有价值的信息,本文进行了一些尝试:利用机器学习方法,自动标注缺失品类的POI数据.例如,门店名称为"好再来牛肉拉面馆"的POI将自动标注"小吃"品类. 机器学习解决问题的一般过程:本文将按照:1)特征表示:2)特征选择:3)基

基于朴素贝叶斯的内容推荐算法

论文出处: http://www.cs.utexas.edu/~ml/papers/libra-sigir-wkshp-99.pdf 引言 这篇文章里面将会详细介绍基于多项式贝叶斯的内容推荐算法的符号以及术语,公式推导以及核心思想,学习如何从文本分类的角度来实现物品推荐.详细了解算法过程后,你应该可以利用里面的公式来计算出某个用户对于单词级别的喜好强度列表(profile),根据这个强度大小来对其他物品(需先用该强度来对该物品做加权算出该物品的喜好强度)做一个推荐的排序,从而得到用户可能最喜欢的