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

来源:互联网 发布:欧脉艾柱 知乎 编辑:程序博客网 时间:2024/04/27 14:34

子图同构算法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 ofv 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;elseM0[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] = 0for (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;}}}// breakif (!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所对应的M0for (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行的其他元素都为0for (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*MBfor (int i = 0; i < raw; i++) {// rawsfor (int j = 0; j < column; j++) {// columnsfor (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++) {// rawsfor (int j = 0; j < column; j++) {// columnstmp_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++) {// rawsfor (int j = 0; j < MA[0].length; j++) {// columnsfor (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++) {// rawsfor (int j = 0; j < MA[0].length; j++) {// columnsif (MA[i][j] == 1) {if (MC[i][j] == 1)continue;elsereturn 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 blocke.printStackTrace();}}}
package ucas.iie.graph.bean;import java.util.ArrayList;public class GraphBean {/** 图的数据格式 *  t # 0 表示第0个图v 0 2v 1 2v 2 2v 3 2v 4 2e 0 1 2e 1 2 2e 2 3 2e 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 2v 1 2v 2 2v 3 2v 4 2e 0 1 2e 1 2 2e 2 3 2e 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 2v 1 2v 2 2v 3 2v 4 2e 0 1 2e 1 2 2e 2 3 2e 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;}}







2 0
原创粉丝点击