基于JAVA WEB的AHP层次分析法实践--核心的计算类

写一个核心的计算类,命名为ahpAnalysis,代码如下:

var ahpAnalysis=function()

{
var checkSingleCR=true;
var checkTotalCR=true;
var normalizeType="和法";
var RI=[0, 0, 0.58, 0.9, 1.12, 1.24, 1.32, 1.41, 1.45, 1.49, 1.52,1.54,1.56,1.58,1.59];
var maxCI=0.55;
var maxCR=0.1;
var modelNodeList=[];
var runTotal=false;

//矩阵归一化(和法)
function normalize(matrix)
{
var row= matrix.length;
var column = matrix[0].length;
var i=0;
var j=0;
var sum=0;

var Sum_column =[];
var w =[];

//和法
if(normalizeType=="和法")
{
for (i= 0; i < column; i++)
{
Sum_column[i] = 0;
for (j = 0; j < row; j++)
{
Sum_column[i] += matrix[j][i];
}
}


//进行归一化,计算特征向量W            
for (i = 0; i < row; i++)
{
w[i] = 0;
for (j = 0;j<column;j++)
{                    
w[i] += matrix[i][j]/Sum_column[j];
}
w[i] /= row;
}
}

//根法
if(normalizeType=="根法")
{
for (i= 0; i < column; i++)
{
Sum_column[i] = 0;
for (j = 0; j < row; j++)
{
Sum_column[i] += matrix[j][i];
}
}


//进行归一化,计算特征向量W
sum=0;
for (i = 0; i < row; i++)
{
w[i] = 1;
for (j = 0;j<column;j++)
{                    
w[i] *= matrix[i][j]/Sum_column[j];
}
w[i]=Math.pow(w[i],1/row);
sum+=w[i];
}

for (i = 0; i < row; i++)
{
w[i]/=sum;
}
}

//幂法
if(normalizeType=="幂法")
{
var w0 =[];
for (i = 0; i < row; i++) 
{
w0[i] = 1.0/row;
}


//一般向量W(k+1)
var w1 =[];

//W(k+1)的归一化向量
var d = 1.0;
var delt = 0.00001;
while (d > delt) 
{
d=0.0;
sum = 0;


//获取向量
for (i = 0; i < row; i++) 
{
w1[i] = 0;
for (j = 0; j < row; j++)
{
w1[i] += matrix[i][j] * w0[j];
}
sum += w1[i];
}


//向量归一化 
for (i = 0; i< row; i++) 
{
w[i] = w1[i] / sum;
d = Math.max(Math.abs(w[i] - w0[i]), d);//最大差值
w0[i] = w[i];//用于下次迭代使用 
}

}
return w;
}

//进行一致性校验
function checkCR(matrix)
{
var res;
var row = matrix.length;
var column = matrix[0].length;

//矩阵归一化
res.w = normalize(matrix);

//计算AW
var aw = [];
for (var i = 0; i < row; i++)
{
aw[i] = 0;
for (var j = 0; j < column; j++)
{
aw[i] += matrix[i][j] * res.w[j];
}
}


res.body = matrix;


//求和
var sum = 0;
for (i = 0; i < row; i++)
{
sum += aw[i] / res.w[i];
}

//最大特征根
res.r = sum / column;

//一致性指标
res.CI = (res.r - column) / (column - 1);


//当前节点的检验系数
var RI=ahpAnalysis.RI[column - 1];

if(RI<=0)
{
res.CR=0;
}
else
{
res.CR = res.CI /RI;
}


if (res.CR < 0.1)
{
res.success = true;
}
else
{
res.success = false;
res.message="一致性系数(CR):" + Math.round(res.CR*10000)/10000+"大于指定的最大一致性比例"+maxCR.toString();
}


return res;
}

//获取节点的层次模型
function getNodeLevel(startNode,allNode)
{
var levelNode=[];

//按层次读取关联接点
getLevel(startNode,0,levelNode,allNode);

//剔除重复的关系选项
var checkedArr=levelNode[0];
for(var level=1;level<levelNode.length;level++)
{
var nodeList=levelNode[level];
var nodeIndex=0;
while(nodeIndex<nodeList.length)
{
var findAtLowLevel=checkLowLevel(nodeList[nodeIndex],checkedArr,allNode);
if(findAtLowLevel)
{
nodeList.splice(nodeIndex,1);
}
else
{
nodeIndex++;
}
}
checkedArr=checkedArr.concat(levelNode[level]);
}
return levelNode;
}

//分析模型
function analysis(startNode,allNode,onlyCheck)
{
var node=null;
var i=0,j=0;

modelNodeList=allNode;

//取得待分析节点列表
var analysisArr=[];
getNodeList(startNode,analysisArr);

if(runTotal)
{
for each(node in analysisArr)
{
node.p=0;
}
}
else
{
for each(node in allNode)
{
node.p=0;
}
}

//按层次排列节点
var levelNode=getNodeLevel(startNode,analysisArr);

//单排序权向量一致性检验
var result=new checkResult;
for(i=0;i<levelNode.length;i++)
{
for(j=0;j<levelNode[i].length;j++)
{
node=levelNode[i][j];

if(node.matrix.length>0)
{
//将文本的矩阵变量转化为数字
var matrix=transformMatrix(node);
if(matrix==null)
{
node.checkStatus=3;
node.statusMark="错误:判断矩阵矩阵错误或者不完全.";
result.success=false;
result.errorList.push("节点【"+node.nodeName+"】判断矩阵错误.");
result.errorCount++;
break;
}

//单排序权向量一致性检验
var res=ahpAnalysis.checkCR(matrix);
node.setProperty("w",res.w.join(","));
node.setProperty("CI",res.CI);
node.setProperty("CR",res.CR);
node.setProperty("r",res.r);

//设置默认权重为0
node.p=0;

if(res.success)
{
node.checkStatus=1;
node.statusMark="一致性校验通过";
result.successCount++;
}
else
{
//如果需要进行一致性检验,则标记为未通过
if(ahpAnalysis.checkSingleCR)
{
node.checkStatus=3;
node.statusMark="错误:"+res.message;
result.success=false;
result.errorList.push("节点【"+node.nodeName+"】未能通过一致性校验");
result.errorCount++;
}
else
{
node.checkStatus=2;
node.statusMark="警告:"+res.message;
result.warringList.push("节点【"+node.nodeName+"】未能通过一致性校验");
result.warringCount++;
}
}
}
else
{
//如果不是方案节点而且有下级节点
if(node.getProperty("type")!="bottom" && node.next.length>0)
{
node.checkStatus=3;
result.success=false;
node.statusMark="错误:节点【"+node.nodeName+"】没有设置判断矩阵";
result.errorList.push("节点【"+node.nodeName+"】没有设置判断矩阵");
result.errorCount++;
}
}
}
}

if(!result.success || onlyCheck)
{
return result;
}

//总排序权向量的一致性检验
if (checkTotalCR)
{
var sumCI= 0;
var sumRI = 0;


//最下一层
var currentList =levelNode[levelNode.Count - 1];


for each(node in currentList)
{
var previousArr = node.previous;
for (i = 0; i < previousArr.length; i++)
{
var currentParentNode=modelNodeList[previousArr[i]];
if(analysisArr.indexOf(currentParentNode)>=0)
{
sumCI += currentParentNode.CI;
sumRI += currentParentNode.RI;
}
}
}


var totalCR = (sumRI > 0) ? sumCI / sumRI : 0;

if (totalCR >= maxCR)
{
result.success=false;
result.message="一致性系数(CR):" + Math.round(totalCR*10000)/10000+"大于指定的最大一致性比例"+maxCR.toString();
return result;
}
}            

//层次总排序
startNode.p=1;
for(i=1;i<levelNode.length;i++)
{
for(j=0;j<levelNode[i].length;j++)
{
node=levelNode[i][j];
previousArr=node.previous;
var weight=0;
for(var count=0;count<previousArr.length;count++)
{
var parentNode=modelNodeList[previousArr[count]];
var p=parentNode.p;
if(analysisArr.indexOf(parentNode)>=0)
{
weight+=parentNode.getWeightByID(node.id)*p;
}
}
node.p=weight;
}
}
return result;
}

//根据选择的节点获取分析树
function getNodeList(startNode,nodeList)
{
if(nodeList.indexOf(startNode)<0)
{
nodeList[startNode.id]=startNode;
}

var nextArr=startNode.next;

//如果有下层节点,则递归加入下层节点
if(nextArr!=null)
{
for(var i=0;i<nextArr.length;i++)
{
getNodeList(modelNodeList[nextArr[i]],nodeList);
}
}
}

//递归生成层次结构
function getLevel(currentNode,currentLevel,levelNode,allNode)
{
//如果本层的数组不存在,则创建它
if(levelNode[currentLevel]==null)
{
levelNode[currentLevel]=[];
}

//已经存在于本层数组中,则返回
if(levelNode[currentLevel].indexOf(currentNode)>=0) return;

//将节点加入当前层
if(allNode.indexOf(currentNode)>=0)
{
currentNode.setProperty("level",currentLevel);
levelNode[currentLevel][levelNode[currentLevel].length]=currentNode;
}

//递归加入下一层
var nextArr=currentNode.next;
if(nextArr!=null)
{
var n=nextArr.length;
for(var i=0;i<n;i++)
{
getLevel(modelNodeList[nextArr[i]],currentLevel+1,levelNode,allNode);
}
}
}

//查找是否具有更底层的链接关系
function checkLowLevel(node,checkedArr,allNode)
{
//遍历节点的上层链接关系
var previousArr=node.previous;
if(previousArr!=null)
{
for(var i=0;i<previousArr.length;i++)
{
var parentNode=modelNodeList[previousArr[i]];

//如果存在链接关系且链接关系不属于已经检查的上层节点集合,则认为此节点主要链接关系在下层
if(allNode.indexOf(parentNode)>=0 && checkedArr.indexOf(parentNode)<0)
{
return true;
}

//递归路径查找
if(checkLowLevel(parentNode,checkedArr,allNode))
{
return true;
}
}
}
return false;
}

//将矩阵的值转化为数字
function transformMatrix(node)
{
var matrix=node.matrix;
var children=node.next;

var row = matrix.length;
var column = matrix[0].length;

if(row!=children.length || column!=children.length)
{
return null;
}

for (var i = 0; i < row; i++)
{               
for (var j = 0; j < column; j++)
{
var n=calculationFormula(matrix[i][j]);
if(!isNaN(n))
{
matrix[i][j]=n;
}
else
{
return null; 
}
}
}
return matrix;
}

//将类似1/3格式的字符串转为数字
function calculationFormula(formula)
{
if (formula.indexOf("/") > 0)
{
var kt = formula.split('/');
return Number(kt[0])/Number(kt[1]);
}
return Number(formula);
}

}

接下来就是一系列的计算和显示的问题了,比较简单就不在博客里面写了。

上一篇:基于JAVA WEB的AHP层次分析法实践--JS的界面组件 下一篇:文章连载已完结,没有下一个了

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值