Java图的邻接矩阵数据转化为指数级的联盟结构数据

本文探讨了如何将图的邻接矩阵数据转换为联盟结构数据,以便于在多Agent系统中进行联盟生成研究。提供了一个Java解决方案,能够处理不同数量的Agent,具有良好的扩展性。通过读取图的邻接矩阵文件,输出联盟结构文件,每个子集的权重按位表示并相加。转化过程的时间复杂度为2的n次方-1,其中n为Agent数量。
摘要由CSDN通过智能技术生成

研究多Agent系统中的图上的联盟结构生成问题时,需要把图的数据转换成传统的联盟形成的数据,才能与传统的方法进行对比试验。
输入一个a.txt文件,文件内容包含一个图的邻接矩阵,如下所示:
0 2 4 8
2 0 4 1
4 4 0 3
8 1 3 0
附:图
在这里插入图片描述

输出一个b.txt文件,文件内容如下所示:

0
0
0
2
0
4
4
10
0
8
1
11
3
15
8
22
说明:
输出时必须每行一个值。
文件中每行代表的含义如下:
0是由0 = 0000表示的子集的值,它是{}
0是由1 = 0001表示的子集的值,它是{a1}
0是由2 = 0010表示的子集的值,即{a2}
2是由3 = 0011表示的子集的值,它是{a1,a2} (即权重)
0是由4 = 0100表示的子集的值,即{a3}
4是由5 = 0101表示的子集的值,它是{a1,a3}
4是由6 = 0110表示的子集的值,它是{a2,a3}
10由7 = 0111表示的子集的值,它是{a1,a2,a3} (权重相加)
0是由8 = 1000表示的子集的值,即{a4}
8是由9 = 1001表示的子集的值,它是{a1,a4}
1是由10 = 1010表示的子集的值,即{a2,a4}
11是由11 = 1011表示的子集的值,它是{a1,a2,a4}
3是由12 = 1100表示的子集的值,它是{a3,a4}
15是由13 = 1101表示的子集的值,它是{a1,a3,a4}
8是由14 = 1110表示的子集的值,它是{a2,a3,a4}
22是由15 = 1111表示的子集的值,它是{a1,a2,a3,a4}

代码具有扩展性,不只适用于4个Agent的情况下,输入10个、20个Agent的图邻接矩阵时也能生成相应的.txt文件。
复杂度为2的n次方-1。
下面展示一些 代码片。共有两个类。

package com;

public class Tset {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		new GetDataFromFile().getDataFromFile();
	}

}

package com;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.Scanner;

/**
 * 输入规范的邻接矩阵数字txt文件,输出每个点对应的值到一个文件中
 * @author 
 * 
 */
public class GetDataFromFile {

	/**
	 * 外部调用方法,输入txt文件路径,输出对应txt文件
	 */
	public void getDataFromFile(){
		try {
			//输入源文件
			File file = this.getFileFromStr();
			//读取源文件,判断源文件是否符合邻接矩阵规范,输出二位数组
			String[][] readFileByLine = this.readFileByLine(file);
			//输出对应点的值到目标文件
			this.dataToFile(readFileByLine, file);
			System.out.println("文件输出结束。");
		} catch (IOException e) {
			//e.printStackTrace();
			System.out.println("出现异常,原因为:" + e.getMessage());
		}
		
	}
	
	/**
	 * 输入文件路径,输出文件对象
	 * @return
	 */
	private File getFileFromStr(){
		@SuppressWarnings("resource")
		Scanner in = new Scanner(System.in);
		System.out.println("请输入文件的绝对路径:");
		String str = in.nextLine();
		File file = new File(str);
		if(file != null && !file.exists() && !file.isFile()){
			System.out.println("您输入的文件路径不合法,请核对后再输入。");
			file = null;
		}
		return file;
	}
	
	/**
	 * 将文件内容输入到一个二维数组
	 * @param file
	 * @return
	 * @throws IOException
	 */
    private String[][] readFileByLine(File file) throws IOException{
    	String[][] splitStr= null;
    	BufferedReader bufferedReader = null;
    	BufferedReader bufferedReaderLen = null;
        try {
            bufferedReader = new BufferedReader(new FileReader(file));
            bufferedReaderLen = new BufferedReader(new FileReader(file));
            String strLine = null;
            int lineCount = 1, lineCountLen = 0;
            while(null != (strLine = bufferedReaderLen.readLine())){
            	lineCountLen++;
            }
            splitStr= new String[lineCountLen][];
            while(null != (strLine = bufferedReader.readLine())){
            	splitStr[lineCount-1] = strLine.replace(" ", ",").replaceAll("\\,+", ",").split(",|,");
            	System.out.println("第[" + lineCount + "]行数据:[" + strLine + "]");
                lineCount++;
            }
            splitStr = this.validFloat(splitStr);
        }catch(Exception e){
        	splitStr = null;
            e.printStackTrace();
        }finally{
        	if(bufferedReader != null)
        		bufferedReader.close();
        	if(bufferedReaderLen != null)
        		bufferedReaderLen.close();
        }
        return splitStr;
    }
    
    /**
     * 检查是不是规范的邻接矩阵
     * @param splitStr
     * @return
     */
    private String[][] validFloat(String[][] splitStr){
    	if(splitStr == null || splitStr.length == 0){
        	System.out.println("文件为空,请核查后输入。");
        	return null;
        }
    	try{
    		for(int i=0,len=splitStr.length; i<len ; i++){
        		if(len != splitStr[i].length){
        			System.out.println("第"+(i+1)+"行的数字个数与列的个数不一致,请核查后修改。");
                	return null;
        		}else{
        			for(int j=0;j<i+1;j++){
        				if(j == i){
        					if(splitStr[i][j] == null || splitStr[i][j].trim().length() == 0){
        						System.out.println("第"+(i+1)+"行第"+(j+1)+"列的对应的数字为空,请核查后修改。");
        						return null;
        					}else{
        						splitStr[i][j] = splitStr[i][j].trim();
        					}
        				}else{
        					if(splitStr[i][j] == null || splitStr[i][j].trim().length() == 0){
        						System.out.println("第"+(i+1)+"行第"+(j+1)+"列的对应的数字为空,请核查后修改。");
        						return null;
        					}else if(splitStr[j][i] == null || splitStr[j][i].trim().length() == 0){
        						System.out.println("第"+(i+1)+"行第"+(j+1)+"列的对应的数字为空,请核查后修改。");
        						return null;
        					}else{
        						splitStr[i][j] = splitStr[i][j].trim();
        						splitStr[j][i] = splitStr[j][i].trim();
        					}
        					if(!splitStr[i][j].equals(splitStr[j][i])){
        						System.out.println("第"+(i+1)+"行第"+(j+1)+"列的对应的数字与第"+(j+1)+"行第"+(i+1)+"列的对应的数字不同,请核查后修改。");
        						return null;
        					}
        				}
        				Float.valueOf(splitStr[i][j]);
        				Float.valueOf(splitStr[j][i]);
        			}
        		}
        	}
		}catch(Exception e){
			splitStr = null;
            e.printStackTrace();
        }
        return splitStr;
    }
    
    /**
     * 计算每个点对应的值并输出到文件
     * @param splitStr
     * @param orgFile
     * @throws IOException
     */
    private void dataToFile(String[][] splitStr,File orgFile) throws IOException{
    	// 创建基于文件的输出流
    	FileOutputStream fos = null;
    	try {
    		String str = orgFile.getAbsolutePath();
    		if(str.indexOf(".txt")>-1){
    			str = str.replace(".txt", "-b.txt");
    		}else{
    			str += "-b";
    		}
            File file = new File(str);
            if (file.exists()==false){
            	file.getParentFile().mkdirs();
            }else{
            	file.delete();
            }
            //byte data[] = null;
            fos = new FileOutputStream(file);
            BigDecimal index = new BigDecimal("0");
            //文件数字的总长度 2的N次方
            int len = 1;
            for(int i=0;i<splitStr.length;i++){
            	len *= 2;
            }
            for(int i=0;i<len;i++){
        		index = this.getIndex(splitStr, i);
        		fos.write((String.valueOf(index)+"\r\n").getBytes());
            }
            fos.flush();
        } catch (IOException e) {
            e.printStackTrace();
        }finally{
        	if(fos != null)
        		// 关闭输出流
        		fos.close();
        }
    }
    
    /**
     * 计算每个点对应的值
     * @param splitStr
     * @param num
     * @return
     */
    private BigDecimal getIndex(String[][] splitStr,int num){
    	//避免精度问题,使用BigDecimal计算
    	BigDecimal fat = new BigDecimal("0");
    	int[] tempStr = new int[splitStr.length];
    	String tenToTwo = this.tenToTwo(num);
    	tenToTwo = new StringBuffer(tenToTwo).reverse().toString();
    	int index = 0;
    	for(int i=0; i<tenToTwo.length();i++){
    		if(tenToTwo.charAt(i) == '1'){
    			tempStr[index] = i; 
    			index++;
    		}
    	}
    	if(tempStr.length > 0){
    		for(int i=0; i<index;i++){
    			for(int j=i; j<index;j++){
    				fat = fat.add(new BigDecimal(splitStr[tempStr[i]][tempStr[j]]));
            	}
        	}
    	}
    	return fat;
    }
    
    /**
     * 十进制转二进制
     * @param num
     * @return
     */
    private String tenToTwo(int num){
    	String a = "";
    	//利用十进制转二进制除2法
		while(num!=0) {
			a=num%2+a;
			num=num/2;
		}
		return a;
    }
    
}


输出结果如下所示:
在这里插入图片描述在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值