码迷,mamicode.com
首页 > 编程语言 > 详细

子图同构算法Ullmann实现,并采取了Refinement(java语言)

时间:2015-01-15 22:15:03      阅读:343      评论:0      收藏:0      [点我收藏+]

标签:ullmann   子图同构算法   ullmann_algorithmiso   

子图同构算法Ullmann早在1976年就提出来了,大家有兴趣可以自己去搜索下原文看看。这里我就简要的阐述一下。

给定两个图Q 和 G, 它们相应的矩阵分别是技术分享技术分享.我们的目标就是找到矩阵技术分享技术分享

算法步骤:

       Step1. Setup matrix Mn×m , such that M[i][j]=1, if 1) the i-th vertex in Q hasthe same label as the j-th vertex in G; and 2) the i-th vertex has smallervertex degree than the j-th vertex in G.

       Step2.MatrixesM are generated by systematically changing to 0 all but one of the 1’s in eachof the rows of M, subject to the definitory condition that no column of amatrix M may contain more than one 1. 

       Step3.Verify matrix M’ by the following equation

                 技术分享

为了提高算法的效率,采用了如下的Refinement。

Refinement:

Letthe i-th vertex v in Q corresponds to the j-th vertex u in G.Each neighbor vertex of v in Q must correspond to some neighbor vertexof u in G.  Otherwise, vcannot correspond to u.

 1. Considering the matrix M, for each 1 in M, we refine it by the followingequation. If fails, change 1 to 0 in M.

       技术分享

 2.  If there exists at least one row (in M) having no 1, we report no subgraphisomorphism from Q to G.

接下来就直接粘贴代码了。


package ucas.iie.graph.action;

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;

import ucas.iie.graph.bean.EdgeBean;
import ucas.iie.graph.bean.GraphBean;
import ucas.iie.graph.bean.VertexBean;

public class IsomorphismImpl {
	private ArrayList<GraphBean> query_g;// 查询的子图
	private ArrayList<GraphBean> mydb_g;// 图的总数据

	public IsomorphismImpl() {
		query_g = new ArrayList<GraphBean>();
		mydb_g = new ArrayList<GraphBean>();
	}

	/**
	 * 
	 * @param query
	 * @param db
	 * @return 返回初始的矩阵M0
	 */
	public int[][] getMatrixM(GraphBean query, GraphBean db) {
		int row = query.getvList().size();
		int column = db.getvList().size();
		int[][] M0 = new int[row][column];
		// System.out.println("M0:");
		for (int i = 0; i < row; i++) {
			for (int j = 0; j < column; j++) {
				String vi = query.getvList().get(i).getVertex();
				String vj = db.getvList().get(j).getVertex();
				if (db.getVDegree(vj) >= query.getVDegree(vi))
					M0[i][j] = 1;
				else
					M0[i][j] = 0;
				// System.out.print(M0[i][j] + " ");
			}
			// System.out.println("");
		}
		return M0;
	}

	public ArrayList<GraphBean> getQuery_g() {
		return query_g;
	}

	public void setQuery_g(ArrayList<GraphBean> query_g) {
		this.query_g = query_g;
	}

	public ArrayList<GraphBean> getMydb_g() {
		return mydb_g;
	}

	public void setMydb_g(ArrayList<GraphBean> mydb_g) {
		this.mydb_g = mydb_g;
	}

	/**
	 * 
	 * @param queryFile
	 *            查询子图的路径
	 * @param dbFile
	 *            图的总数据路径
	 * @throws IOException
	 */
	public void initGraphDB(String queryFile, String dbFile) throws IOException {
		// 读取查询子图的数据
		BufferedReader q_br = new BufferedReader(new InputStreamReader(
				new FileInputStream(queryFile)));
		String lineData = q_br.readLine();
		GraphBean qgb;
		if (lineData.startsWith("t #")) {// 第一个子图
			qgb = new GraphBean();
			while ((lineData = q_br.readLine()) != null) {
				if (lineData.startsWith("t #")) {
					this.query_g.add(qgb);
					qgb = new GraphBean();
					continue;
				} else if (lineData.startsWith("v")) { // 顶点
					String vs[] = lineData.split(" ");
					VertexBean vb = new VertexBean();
					vb.setVertex(vs[1]);
					vb.setLabel(vs[2]);
					qgb.getvList().add(vb);
				} else { // 边
					String es[] = lineData.split(" ");
					EdgeBean eb = new EdgeBean();
					eb.setVertex_i(es[1]);
					eb.setVertex_j(es[2]);
					eb.setLabel_e(es[3]);
					qgb.geteList().add(eb);
				}
			}
		}

		// 读取图数据
		BufferedReader db_br = new BufferedReader(new InputStreamReader(
				new FileInputStream(dbFile)));
		lineData = db_br.readLine();
		GraphBean dbgb;
		if (lineData.startsWith("t #")) {//
			dbgb = new GraphBean();
			while ((lineData = db_br.readLine()) != null) {
				if (lineData.startsWith("t #")) {
					this.mydb_g.add(dbgb);
					dbgb = new GraphBean();
					continue;
				} else if (lineData.startsWith("v")) { // 顶点
					String vs[] = lineData.split(" ");
					VertexBean vb = new VertexBean();
					vb.setVertex(vs[1]);
					vb.setLabel(vs[2]);
					dbgb.getvList().add(vb);
				} else if (lineData.startsWith("e")) { // 边
					String es[] = lineData.split(" ");
					EdgeBean eb = new EdgeBean();
					eb.setVertex_i(es[1]);
					eb.setVertex_j(es[2]);
					eb.setLabel_e(es[3]);
					dbgb.geteList().add(eb);
				}
			}
		}
	}

	/**
	 * 返回边的label
	 * @param i
	 * @param j
	 * @param ebList
	 * @return
	 */
	public String getLabel(String i, String j, ArrayList<EdgeBean> ebList) {
		for (int k = 0; k < ebList.size(); k++) {
			EdgeBean eb = ebList.get(k);
			String vi = eb.getVertex_i();
			String vj = eb.getVertex_j();
			if (i.equals(vi) && j.equals(vj))
				return eb.getLabel_e();
			else if (j.equals(vi) && i.equals(vj))
				return eb.getLabel_e();
		}
		return null;
	}

	public boolean isIsomorphism(GraphBean subgraph, GraphBean graphdb) {
		int M0[][] = getMatrixM(subgraph, graphdb);
		int MA[][] = subgraph.getMatrix();
		int MB[][] = graphdb.getMatrix();
		ArrayList<EdgeBean> ebq = subgraph.geteList();
		ArrayList<EdgeBean> ebdb = graphdb.geteList();
		// 对任意的MA[i][x] = 1 ==> 存在y M[x][y]MB[y][j] = 1 否则M0[i][j] = 0
		for (int i = 0; i < subgraph.getvList().size(); i++) {
			for (int j = 0; j < graphdb.getvList().size(); j++) {
				if (M0[i][j] == 1) {
					String ilabel = subgraph.getvList().get(i).getLabel();
					String jlabel = graphdb.getvList().get(j).getLabel();
					if (ilabel.equals(jlabel)) {
						for (int x = 0; x < subgraph.getvList().size(); x++) {
							boolean tag = false;
							if (MA[i][x] == 1) {
								String label_ix = getLabel(String.valueOf(i),
										String.valueOf(x), ebq);
								for (int y = 0; y < graphdb.getvList().size(); y++) {
									if (M0[x][y] * MB[y][j] == 1) {
										String label_yj = getLabel(
												String.valueOf(y),
												String.valueOf(j), ebdb);
										if (label_ix.equals(label_yj)) {///比较顶点之间的边上的标签,看是否相等。
											tag = true;
											break;
										}
									}
								}// break
								if (!tag) {
									M0[i][j] = 0;
									break;
								}
							}
						}// break
					} else {// if(ilabel.equals(jlabel))
						M0[i][j] = 0;
					}
				}// if (M0[i][j] == 1)
			}
		}
		// System.out.println("M':");
		for (int i = 0; i < subgraph.getvList().size(); i++) {
			int sumi = 0;
			for (int j = 0; j < graphdb.getvList().size(); j++) {
				// System.out.print(M0[i][j] + " ");
				sumi += M0[i][j];
			}
			if (sumi == 0) {
				// System.out.println("M0有一行元素都是0");
				return false;
			}// 有一行的元素都是0,直接退出
				// System.out.println();
		}
		int raw = subgraph.getvList().size();
		int col = graphdb.getvList().size();
		int F[] = new int[col];// F[i] = 1 ,表示第i列已经用过了
		int H[] = new int[raw];// H[d] = k ,表示第d行选的是第k列
		int d = 0;// M0的第d行
		int k = 0;// M0的第k列
		int[][][] matrixList = new int[raw][][];// 用来记录每次d所对应的M0
		for (int i = 0; i < F.length; i++) {
			F[i] = -1;
		}
		for (int i = 0; i < H.length; i++) {
			H[i] = -1;
		}

		// //////////////////////////////
		while (true) {

			if (H[d] == -1) {
				k = 0;
				matrixList[d] = M0;
			} else {// 回溯
				k = H[d] + 1;
				F[H[d]] = -1;
				M0 = matrixList[d];

			}

			while (k < col) {// 也就是M0的列
				if (M0[d][k] == 1 && F[k] == -1) {// 这样的列找到后就跳出,其他的在回溯的时候再遍历
					break;
				}
				k++;
			}

			if (k == col) {// 第d行中没有满足条件的列,回溯到上一层
				H[d] = -1;
				d--;
			} else {// M0[d][k]=1,第d行的其他元素都为0
				for (int j = 0; j < col; j++) {
					M0[d][j] = 0;
				}
				M0[d][k] = 1;
				H[d] = k;
				F[k] = 1;
				d++;
			}

			if (d == -1) {
				// System.out.println("不同构");
				return false;
			}

			if (d == raw) {// 即找到了一个M0,接下里就是验证
				if (this.isTrueFor(MA, MB, M0)) {// 条件成立
					// System.out.println("同构");
					return true;
				} else {// 回溯
					d = raw - 1;
				}

			}// if
		}// while
	}

	/**
	 * for all element int MA[i][j]=1 ==> MC=M*{(M*MB)^T},MC[i][j]=1
	 * 
	 * @param MA
	 * @param MB
	 * @param M
	 * @return
	 */
	public boolean isTrueFor(int[][] MA, int[][] MB, int M[][]) {
		boolean flag = true;
		int raw = M.length;
		int column = MB[0].length;
		int tmp[][] = new int[raw][column];// tmp[][]=M*MB
		for (int i = 0; i < raw; i++) {// raws
			for (int j = 0; j < column; j++) {// columns
				for (int k = 0; k < M[0].length; k++) {
					tmp[i][j] += M[i][k] * MB[k][j];
				}
			}
		}
		int tmp_t[][] = new int[column][raw];// 转置
		for (int i = 0; i < raw; i++) {// raws
			for (int j = 0; j < column; j++) {// columns
				tmp_t[j][i] = tmp[i][j];
			}
		}
		int MC[][] = new int[MA.length][MA[0].length];
		// System.out.println("MC:");
		for (int i = 0; i < MA.length; i++) {// raws
			for (int j = 0; j < MA[0].length; j++) {// columns
				for (int k = 0; k < M[0].length; k++) {
					MC[i][j] += M[i][k] * tmp_t[k][j];
				}
				// System.out.print(MC[i][j] + " ");
			}
			// System.out.println();
		}
		for (int i = 0; i < MA.length; i++) {// raws
			for (int j = 0; j < MA[0].length; j++) {// columns
				if (MA[i][j] == 1) {
					if (MC[i][j] == 1)
						continue;
					else
						return false;
				}
			}

		}
		return flag;
	}

	public static void main(String[] args) {
		IsomorphismImpl ii = new IsomorphismImpl();
		String queryFile = "C:\\Users\\Fernando\\Desktop\\Q24.my";
		String dbFile = "C:\\Users\\Fernando\\Desktop\\mygraphdb.data";
		try {
			ii.initGraphDB(queryFile, dbFile);
			ArrayList<GraphBean> query_g = ii.getQuery_g();
			System.out.println("子图(size):" + query_g.size());
			ArrayList<GraphBean> db_g = ii.getMydb_g();
			System.out.println("总图(size):" + db_g.size());
			for (int i = 0; i < query_g.size(); i++) {
				for (int j = 0; j < db_g.size(); j++) {
					GraphBean tq = query_g.get(i);
					GraphBean tdb = db_g.get(j);
					if (ii.isIsomorphism(tq, tdb)) {
						System.err.println("t # " + i + " 与  T # " + j + " 同构");
					}
				}
			}
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}
package ucas.iie.graph.bean;

import java.util.ArrayList;

public class GraphBean {
	/** 图的数据格式
	 *  t # 0 表示第0个图
		v 0 2
		v 1 2
		v 2 2
		v 3 2
		v 4 2
		e 0 1 2
		e 1 2 2
		e 2 3 2
		e 3 4 2
	 */
	private ArrayList<VertexBean> vList;
	private ArrayList<EdgeBean> eList;
	public GraphBean(){
		vList = new ArrayList<VertexBean>();
		eList = new ArrayList<EdgeBean>();
	}
	public ArrayList<VertexBean> getvList() {
		return vList;
	}
	public void setvList(ArrayList<VertexBean> vList) {
		this.vList = vList;
	}
	public ArrayList<EdgeBean> geteList() {
		return eList;
	}
	public void seteList(ArrayList<EdgeBean> eList) {
		this.eList = eList;
	}	
	public int[][] getMatrix(){
		int[][] M = new int[vList.size()][vList.size()];
		for (int index = 0; index < eList.size(); index++) {
			EdgeBean eb = eList.get(index);
			int i = Integer.parseInt(eb.getVertex_i());
			int j = Integer.parseInt(eb.getVertex_j());
			M[i][j] = 1;
			M[j][i] = 1;
		}
//		System.out.println("MA/MB:");
//		for (int i = 0; i < vList.size(); i++) {
//			for (int j = 0; j < vList.size(); j++) {
//				System.out.print(M[i][j] + " ");
//			}
//			System.out.println();
//		}
		return M;
	}
	/**
	 * 
	 * @param v
	 * @return 返回顶点v的度
	 */
	public int getVDegree(String v){
		int sumDeg = 0;
		for (int i = 0; i < eList.size(); i++) {
			if(eList.get(i).getVertex_i().equals(v)||
					eList.get(i).getVertex_j().equals(v)){
				sumDeg ++;
			}
		}
		return sumDeg;
	}
	public String toString(){
		String res = "";
		for (int i = 0; i < this.vList.size(); i++) {
			res +="v " + vList.get(i).getVertex()  + " " + vList.get(i).getLabel() + "\r\n";
		}
		for (int j = 0; j < this.eList.size(); j++) {
			res +="e " + eList.get(j).getVertex_i()  + " " + eList.get(j).getVertex_j() + " "+eList.get(j).getLabel_e() + "\r\n";
		}
		return res;
	}
	public static void main(String[] args) {
		new GraphBean().getMatrix();
	}
}

package ucas.iie.graph.bean;

public class EdgeBean {//“e i j k” 表示图的边<i,j>的label是k 
	/** 图的数据格式
	 *  t # 0 表示第0个图
		v 0 2
		v 1 2
		v 2 2
		v 3 2
		v 4 2
		e 0 1 2
		e 1 2 2
		e 2 3 2
		e 3 4 2
	 */
	private String vertex_i;
	private String vertex_j;
	private String label_e;
	public String getVertex_i() {
		return vertex_i;
	}
	public void setVertex_i(String vertex_i) {
		this.vertex_i = vertex_i;
	}
	public String getVertex_j() {
		return vertex_j;
	}
	public void setVertex_j(String vertex_j) {
		this.vertex_j = vertex_j;
	}
	public String getLabel_e() {
		return label_e;
	}
	public void setLabel_e(String label_e) {
		this.label_e = label_e;
	}
}

package ucas.iie.graph.bean;
public class VertexBean { //“v i j” 表示图的顶点i的label是j 
	/** 图的数据格式
	 *  t # 0 表示第0个图
		v 0 2
		v 1 2
		v 2 2
		v 3 2
		v 4 2
		e 0 1 2
		e 1 2 2
		e 2 3 2
		e 3 4 2
	 */
	private String vertex;
	private String label;
	public String getVertex() {
		return vertex;
	}
	public void setVertex(String vertex) {
		this.vertex = vertex;
	}
	public String getLabel() {
		return label;
	}
	public void setLabel(String label) {
		this.label = label;
	}
	
}







子图同构算法Ullmann实现,并采取了Refinement(java语言)

标签:ullmann   子图同构算法   ullmann_algorithmiso   

原文地址:http://blog.csdn.net/sh_c1991/article/details/42746429

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!