研究多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;
}
}
输出结果如下所示: