From 1defa326278a5a0687a57555d4d2eae126873f83 Mon Sep 17 00:00:00 2001 From: Benoit GAUZERE Date: Fri, 10 Nov 2017 14:38:33 +0100 Subject: [PATCH 01/16] add README --- README.md | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 README.md diff --git a/README.md b/README.md new file mode 100644 index 0000000..e69de29 From 91cb5d2ee64bae285b3d633c0f98543ad41aa9b6 Mon Sep 17 00:00:00 2001 From: Benoit GAUZERE Date: Fri, 10 Nov 2017 14:57:02 +0100 Subject: [PATCH 02/16] First init - may contains some errors... --- ged/GED.py | 74 ++++++++++++++++++++ ged/bipartiteGED.py | 33 +++++++++ ged/costfunctions.py | 133 +++++++++++++++++++++++++++++++++++ kernels/.gitignore | 0 notebooks/paths.py | 3 + notebooks/test_lib.ipynb | 175 +++++++++++++++++++++++++++++++++++++++++++++++ utils/graphfiles.py | 74 ++++++++++++++++++++ utils/utils.py | 10 +++ 8 files changed, 502 insertions(+) create mode 100644 ged/GED.py create mode 100644 ged/bipartiteGED.py create mode 100644 ged/costfunctions.py create mode 100644 kernels/.gitignore create mode 100644 notebooks/paths.py create mode 100644 notebooks/test_lib.ipynb create mode 100644 utils/graphfiles.py create mode 100644 utils/utils.py diff --git a/ged/GED.py b/ged/GED.py new file mode 100644 index 0000000..69dbeb2 --- /dev/null +++ b/ged/GED.py @@ -0,0 +1,74 @@ +from ged.costfunctions import BasicCostFunction, RiesenCostFunction +from ged.costfunctions import NeighboorhoodCostFunction +from ged.bipartiteGED import computeBipartiteCostMatrix, getOptimalMapping + + +def ged(G1, G2, method='Riesen', rho=None, varrho=None, + cf=BasicCostFunction(1, 3, 1, 3)): + """Compute Graph Edit Distance between G1 and G2 according to mapping + encoded within rho and varrho. Graph's node must be indexed by a + index which is used is rho and varrho + NB: Utilisation de + dictionnaire pour etre plus versatile ? + + """ + if ((rho is None) or (varrho is None)): + if(method == 'Riesen'): + cf_bp = RiesenCostFunction(cf) + elif(method == 'Neighboorhood'): + cf_bp = NeighboorhoodCostFunction(cf) + elif(method == 'Basic'): + cf_bp = cf + else: + raise NameError('Non existent method ') + + rho, varrho = getOptimalMapping(computeBipartiteCostMatrix(G1, G2, cf_bp)) + + n = G1.number_of_nodes() + m = G2.number_of_nodes() + ged = 0 + for i in G1.nodes_iter(): + phi_i = rho[i] + if(phi_i >= m): + ged += cf.cnd(i, G1) + else: + ged += cf.cns(i, phi_i, G1, G2) + for j in G2.nodes_iter(): + phi_j = varrho[j] + if(phi_j >= n): + ged += cf.cni(j, G2) + + for e in G1.edges_iter(data=True): + i = e[0] + j = e[1] + phi_i = rho[i] + phi_j = rho[j] + if (phi_i < m) and (phi_j < m): + mappedEdge = len(list(filter(lambda x: True if + x == phi_j else False, G2[phi_i]))) + if(mappedEdge): + e2 = [phi_i, phi_j, G2[phi_i][phi_j]] + min_cost = min(cf.ces(e, e2, G1, G2), + cf.ced(e, G1), cf.cei(e2, G2)) + ged += min_cost + else: + ged += cf.ced(e, G1) + else: + ged += cf.ced(e, G1) + for e in G2.edges_iter(data=True): + i = e[0] + j = e[1] + phi_i = varrho[i] + phi_j = varrho[j] + if (phi_i < n) and (phi_j < n): + mappedEdge = len(list(filter(lambda x: True if x == phi_j + else False, G1[phi_i]))) + if(not mappedEdge): + ged += cf.cei(e, G2) + else: + ged += cf.ced(e, G2) + return ged, rho, varrho + + +def computeDistanceMatrix(dataset): + pass diff --git a/ged/bipartiteGED.py b/ged/bipartiteGED.py new file mode 100644 index 0000000..2599eb0 --- /dev/null +++ b/ged/bipartiteGED.py @@ -0,0 +1,33 @@ +import numpy as np +from scipy.optimize import linear_sum_assignment +from ged.costfunctions import BasicCostFunction + + +def computeBipartiteCostMatrix(G1, G2, cf=BasicCostFunction(1, 3, 1, 3)): + """Compute a Cost Matrix according to cost function cf""" + n = G1.number_of_nodes() + m = G2.number_of_nodes() + nm = n + m + C = np.ones([nm, nm])*np.inf + C[n:, m:] = 0 + + for u in G1.nodes_iter(): + for v in G2.nodes_iter(): + cost = cf.cns(u, v, G1, G2) + C[u, v] = cost + + for v in G1.nodes_iter(): + C[v, m + v] = cf.cnd(v, G1) + + for v in G2.nodes_iter(): + C[n + v, v] = cf.cni(v, G2) + return C + + +def getOptimalMapping(C): + """Compute an optimal linear mapping according to cost Matrix C + inclure les progs C de Seb + + """ + row_ind, col_ind = linear_sum_assignment(C) + return col_ind, row_ind[np.argsort(col_ind)] diff --git a/ged/costfunctions.py b/ged/costfunctions.py new file mode 100644 index 0000000..4d2be90 --- /dev/null +++ b/ged/costfunctions.py @@ -0,0 +1,133 @@ +import numpy as np +from scipy.optimize import linear_sum_assignment + + +class BasicCostFunction: + def __init__(self, cns, cni, ces, cei): + self.cns_ = cns + self.cni_ = self.cnd_ = cni + self.ces_ = ces + self.cei_ = self.ced_ = cei + + def cns(self, u, v, G1, G2): + return (G1.node[u]['label'] != G2.node[v]['label'])*self.cns_ + + def cnd(self, u, G1): + return self.cnd_ + + def cni(self, v, G2): + return self.cni_ + + def ces(self, e1, e2, G1, G2): + """tester avec des attributs autres que symboliques en testant + l'operateur __eq__""" + return (e1[2]['label'] != e2[2]['label'])*self.ces_ + + def ced(self, e1, G1): + return self.ced_ + + def cei(self, e2, G2): + return self.cei_ + + +class RiesenCostFunction(BasicCostFunction): + def __init__(self, cf): + BasicCostFunction.__init__(self, cf.cns_, cf.cni_, cf.ces_, cf.cei_) + + def cns(self, u, v, G1, G2): + """ u et v sont des id de noeuds """ + n = len(G1[u]) + m = len(G2[v]) + sub_C = np.ones([n+m, n+m]) * np.inf + sub_C[n:, m:] = 0 + i = 0 + l_nbr_u = G1[u] + l_nbr_v = G2[v] + for nbr_u in l_nbr_u: + j = 0 + e1 = [u, nbr_u, G1[u][nbr_u]] + for nbr_v in G2[v]: + e2 = [v, nbr_v, G2[v][nbr_v]] + sub_C[i, j] = self.ces(e1, e2, G1, G2) + j += 1 + i += 1 + + i = 0 + for nbr_u in l_nbr_u: + sub_C[i, m+i] = self.ced([u, nbr_u, G1[u][nbr_u]], G1) + i += 1 + + j = 0 + for nbr_v in l_nbr_v: + sub_C[n+j, j] = self.cei([v, nbr_v, G2[v][nbr_v]], G2) + j += 1 + row_ind, col_ind = linear_sum_assignment(sub_C) + cost = np.sum(sub_C[row_ind, col_ind]) + return BasicCostFunction.cns(self, u, v, G1, G2) + cost + + def cnd(self, u, G1): + cost = 0 + for nbr in G1[u]: + cost += BasicCostFunction.ced(self,[u,nbr,G1[u][nbr]],G1) + + return BasicCostFunction.cnd(self,u,G1) + cost + + def cni(self, v, G2): + cost = 0 + for nbr in G2[v]: + cost += BasicCostFunction.cei(self, [v,nbr,G2[v][nbr]], G2) + + return BasicCostFunction.cni(self, v, G2) + cost + + +class NeighboorhoodCostFunction(BasicCostFunction): + def __init__(self, cf): + BasicCostFunction.__init__(self, cf.cns_, cf.cni_, cf.ces_, cf.cei_) + + def cns(self, u, v, G1, G2): + """ u et v sont des id de noeuds """ + n = len(G1[u]) + m = len(G2[v]) + sub_C = np.ones([n+m, n+m]) * np.inf + sub_C[n:, m:] = 0 + i = 0 + l_nbr_u = G1[u] + l_nbr_v = G2[v] + for nbr_u in l_nbr_u: + j = 0 + e1 = [u, nbr_u, G1[u][nbr_u]] + for nbr_v in G2[v]: + e2 = [v, nbr_v, G2[v][nbr_v]] + sub_C[i, j] = self.ces(e1, e2, G1, G2) + sub_C[i, j] += BasicCostFunction.cns(self, + nbr_u, nbr_v, G1, G2) + j += 1 + i += 1 + + i = 0 + for nbr_u in l_nbr_u: + sub_C[i, m+i] = self.ced([u, nbr_u, G1[u][nbr_u]], G1) + sub_C[i, m+i] += BasicCostFunction.cnd(self, nbr_u, G1) + i += 1 + + j = 0 + for nbr_v in l_nbr_v: + sub_C[n+j, j] = self.cei([v, nbr_v, G2[v][nbr_v]], G2) + sub_C[n+j, j] += BasicCostFunction.cni(self, nbr_v, G2) + j += 1 + + row_ind, col_ind = linear_sum_assignment(sub_C) + cost = np.sum(sub_C[row_ind, col_ind]) + return BasicCostFunction.cns(self, u, v, G1, G2) + cost + + def cnd(self, u, G1): + cost = 0 + for nbr in G1[u]: + cost += BasicCostFunction.ced(self, [u, nbr, G1[u][nbr]], G1) + return BasicCostFunction.cnd(self, u, G1) + cost + + def cni(self, v, G2): + cost = 0 + for nbr in G2[v]: + cost += BasicCostFunction.cei(self, [v, nbr, G2[v][nbr]], G2) + return BasicCostFunction.cni(self, v, G2) + cost diff --git a/kernels/.gitignore b/kernels/.gitignore new file mode 100644 index 0000000..e69de29 diff --git a/notebooks/paths.py b/notebooks/paths.py new file mode 100644 index 0000000..d8cfdf5 --- /dev/null +++ b/notebooks/paths.py @@ -0,0 +1,3 @@ +import sys +import pathlib +sys.path.insert(0, "../") diff --git a/notebooks/test_lib.ipynb b/notebooks/test_lib.ipynb new file mode 100644 index 0000000..653a43b --- /dev/null +++ b/notebooks/test_lib.ipynb @@ -0,0 +1,175 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 7, + "metadata": { + "autoscroll": false, + "ein.tags": "worksheet-0", + "slideshow": { + "slide_type": "-" + } + }, + "outputs": [], + "source": [ + "import numpy as np\n", + "\n", + "import paths\n", + "\n", + "from ged.GED import ged\n", + "from utils.graphfiles import loadDataset\n", + "from ged.costfunctions import RiesenCostFunction, BasicCostFunction\n", + "from ged.bipartiteGED import computeBipartiteCostMatrix, getOptimalMapping" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": { + "autoscroll": false, + "ein.tags": "worksheet-0", + "slideshow": { + "slide_type": "-" + } + }, + "outputs": [ + { + "data": { + "image/png": "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\n", + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[0, 1, 4]\n" + ] + } + ], + "source": [ + "import networkx as nx\n", + "import numpy as np\n", + "import matplotlib.pyplot as plt\n", + "dataset, y = loadDataset(\"/home/bgauzere/work/Datasets/Acyclic/dataset_bps.ds\")\n", + "nx.draw_networkx(dataset[12])\n", + "plt.show()\n", + "print(list(dataset[12][3]))" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": { + "autoscroll": false, + "ein.tags": "worksheet-0", + "slideshow": { + "slide_type": "-" + } + }, + "outputs": [], + "source": [ + "cf = BasicCostFunction(1,3,1,3)\n", + "N=len(dataset)\n", + "N=10\n", + "ged_distances = np.zeros((N,N))\n", + "for i in range(0,N):\n", + " for j in range(i,N):\n", + " ged_distances[j,i] = ged_distances[i,j] = ged(dataset[i],dataset[j],cf=cf, method='Riesen')[0]\n", + " \n" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": { + "autoscroll": false, + "ein.tags": "worksheet-0", + "slideshow": { + "slide_type": "-" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "(0, array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]), array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]))\n", + "(0, array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]), array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]))\n", + "(0, array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]), array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]))\n" + ] + } + ], + "source": [ + "G1=dataset[12]\n", + "G2=dataset[12]\n", + "\n", + "print(ged(G1,G2))\n", + "print(ged(G1,G2,method='Basic'))\n", + "print(ged(G1,G2,method='Riesen'))\n" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": { + "autoscroll": false, + "ein.tags": "worksheet-0", + "slideshow": { + "slide_type": "-" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{0: {0: [0], 3: [0, 3], 1: [0, 3, 1], 4: [0, 3, 4], 2: [0, 3, 4, 2]}, 1: {1: [1], 3: [1, 3], 0: [1, 3, 0], 4: [1, 3, 4], 2: [1, 3, 4, 2]}, 2: {2: [2], 4: [2, 4], 3: [2, 4, 3], 0: [2, 4, 3, 0], 1: [2, 4, 3, 1]}, 3: {3: [3], 0: [3, 0], 1: [3, 1], 4: [3, 4], 2: [3, 4, 2]}, 4: {4: [4], 2: [4, 2], 3: [4, 3], 0: [4, 3, 0], 1: [4, 3, 1]}}\n", + "[[ 0. 2. 3. 1. 2.]\n", + " [ 2. 0. 3. 1. 2.]\n", + " [ 3. 3. 0. 2. 1.]\n", + " [ 1. 1. 2. 0. 1.]\n", + " [ 2. 2. 1. 1. 0.]]\n" + ] + } + ], + "source": [ + "l = nx.shortest_path(G1)\n", + "print(l)\n", + "\n", + "distances = np.zeros((G1.number_of_nodes(),G1.number_of_nodes()))\n", + "for i in l.keys():\n", + " for j in l[i].keys():\n", + " distances[i,j] = len(l[i][j])-1\n", + "\n", + "print(distances)\n" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.6.2" + }, + "name": "test_lib.ipynb" + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/utils/graphfiles.py b/utils/graphfiles.py new file mode 100644 index 0000000..b561f38 --- /dev/null +++ b/utils/graphfiles.py @@ -0,0 +1,74 @@ +import networkx as nx + + +def loadCT(filename): + content = open(filename).read().splitlines() + G = nx.Graph(name=str(content[0])) + tmp = content[1].split(" ") + if tmp[0] == '': + nb_nodes = int(tmp[1]) + nb_edges = int(tmp[2]) + else: + nb_nodes = int(tmp[0]) + nb_edges = int(tmp[1]) + + for i in range(0, nb_nodes): + tmp = content[i + 2].split(" ") + tmp = [x for x in tmp if x != ''] + G.add_node(i, label=tmp[3]) + + for i in range(0, nb_edges): + tmp = content[i+G.number_of_nodes()+2].split(" ") + tmp = [x for x in tmp if x != ''] + G.add_edge(int(tmp[0]) - 1, int(tmp[1]) - 1, label=int(tmp[3])) + return G + + +def loadGXL(filename): + import networkx as nx + import xml.etree.ElementTree as ET + + tree = ET.parse(filename) + root = tree.getroot() + index = 0 + G = nx.Graph() + dic={} + for node in root.iter('node'): + label = node.find('attr')[0].text + dic[node.attrib['id']] = index + G.add_node(index, id=node.attrib['id'], label=label) + index += 1 + + for edge in root.iter('edge'): + label = edge.find('attr')[0].text + G.add_edge(dic[edge.attrib['from']], dic[edge.attrib['to']], label=label) + return G + + +def loadDataset(filename): + from os.path import dirname, splitext + + dirname_dataset = dirname(filename) + extension = splitext(filename)[1][1:] + data = [] + y = [] + if(extension == "ds"): + content = open(filename).read().splitlines() + for i in range(0, len(content)): + tmp = content[i].split(' ') + data.append(loadCT(dirname_dataset + '/' + tmp[0])) + y.append(float(tmp[1])) + elif(extension == "cxl"): + import xml.etree.ElementTree as ET + + tree = ET.parse(filename) + root = tree.getroot() + data = [] + y = [] + for graph in root.iter('print'): + mol_filename = graph.attrib['file'] + mol_class = graph.attrib['class'] + data.append(loadGXL(dirname_dataset + '/' + mol_filename)) + y.append(mol_class) + + return data, y diff --git a/utils/utils.py b/utils/utils.py new file mode 100644 index 0000000..d9145b9 --- /dev/null +++ b/utils/utils.py @@ -0,0 +1,10 @@ +import networkx as nx +import numpy as np + + +def getSPLengths(G1): + sp = nx.shortest_path(G1) + distances = np.zeros((G1.number_of_nodes(), G1.number_of_nodes())) + for i in np.keys(): + for j in np[i].keys(): + distances[i, j] = len(sp[i][j])-1 From 51a0f0b3e8bff9c0b686d4c16043e8a8871bb3ee Mon Sep 17 00:00:00 2001 From: Benoit GAUZERE Date: Thu, 16 Nov 2017 17:09:27 +0100 Subject: [PATCH 03/16] Minor bug on comparaison between sub and del costs for edges --- ged/GED.py | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/ged/GED.py b/ged/GED.py index 69dbeb2..3e82942 100644 --- a/ged/GED.py +++ b/ged/GED.py @@ -1,10 +1,11 @@ from ged.costfunctions import BasicCostFunction, RiesenCostFunction from ged.costfunctions import NeighboorhoodCostFunction from ged.bipartiteGED import computeBipartiteCostMatrix, getOptimalMapping - +from scipy.optimize import linear_sum_assignment def ged(G1, G2, method='Riesen', rho=None, varrho=None, - cf=BasicCostFunction(1, 3, 1, 3)): + cf=BasicCostFunction(1, 3, 1, 3), + solver=linear_sum_assignment): """Compute Graph Edit Distance between G1 and G2 according to mapping encoded within rho and varrho. Graph's node must be indexed by a index which is used is rho and varrho @@ -14,15 +15,16 @@ def ged(G1, G2, method='Riesen', rho=None, varrho=None, """ if ((rho is None) or (varrho is None)): if(method == 'Riesen'): - cf_bp = RiesenCostFunction(cf) + cf_bp = RiesenCostFunction(cf,lsap_solver=solver) elif(method == 'Neighboorhood'): - cf_bp = NeighboorhoodCostFunction(cf) + cf_bp = NeighboorhoodCostFunction(cf,lsap_solver=solver) elif(method == 'Basic'): cf_bp = cf else: raise NameError('Non existent method ') - rho, varrho = getOptimalMapping(computeBipartiteCostMatrix(G1, G2, cf_bp)) + rho, varrho = getOptimalMapping( + computeBipartiteCostMatrix(G1, G2, cf_bp), lsap_solver=solver) n = G1.number_of_nodes() m = G2.number_of_nodes() @@ -49,7 +51,7 @@ def ged(G1, G2, method='Riesen', rho=None, varrho=None, if(mappedEdge): e2 = [phi_i, phi_j, G2[phi_i][phi_j]] min_cost = min(cf.ces(e, e2, G1, G2), - cf.ced(e, G1), cf.cei(e2, G2)) + cf.ced(e, G1) + cf.cei(e2, G2)) ged += min_cost else: ged += cf.ced(e, G1) From 46c21bf1134f918a2de1828b138922c8afba777f Mon Sep 17 00:00:00 2001 From: Benoit GAUZERE Date: Thu, 16 Nov 2017 17:46:39 +0100 Subject: [PATCH 04/16] Add of a first binder to C++ implementations of LSAP algorithms --- c_ext/Makefile | 5 +++++ c_ext/lsap.cpp | 43 +++++++++++++++++++++++++++++++++++++++++++ c_ext/lsape_binders.py | 23 +++++++++++++++++++++++ 3 files changed, 71 insertions(+) create mode 100644 c_ext/Makefile create mode 100644 c_ext/lsap.cpp create mode 100644 c_ext/lsape_binders.py diff --git a/c_ext/Makefile b/c_ext/Makefile new file mode 100644 index 0000000..71c3eb6 --- /dev/null +++ b/c_ext/Makefile @@ -0,0 +1,5 @@ +# You must specify your env variable LSAPE_DIR +#LSAPE_DIR=/home/bgauzere/Téléchargements/lsape/include/ + +liblsap.so:lsap.cpp + g++ -fPIC -I/home/bgauzere/Téléchargements/lsape/include/ -shared lsap.cpp -o liblsap.so -O3 -I$(LSAPE_DIR) diff --git a/c_ext/lsap.cpp b/c_ext/lsap.cpp new file mode 100644 index 0000000..712a092 --- /dev/null +++ b/c_ext/lsap.cpp @@ -0,0 +1,43 @@ +/* +Python wrapper +*/ + +#include "hungarian-lsape.hh" +#include "hungarian-lsap.hh" + +#include + +extern "C" int lsap(double * C, const int nm, long * rho, long * varrho){ + double * u = new double[nm]; + double * v = new double[nm]; + + int * rho_int = new int[nm]; + int * varrho_int = new int[nm]; + + hungarianLSAP(C,nm,nm,rho_int,u,v,varrho_int); + //Find a better way to do + for (int i =0;i Date: Thu, 16 Nov 2017 17:47:14 +0100 Subject: [PATCH 05/16] Adding a generic lsap solver as parameter --- ged/bipartiteGED.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ged/bipartiteGED.py b/ged/bipartiteGED.py index 2599eb0..1372b7e 100644 --- a/ged/bipartiteGED.py +++ b/ged/bipartiteGED.py @@ -24,10 +24,10 @@ def computeBipartiteCostMatrix(G1, G2, cf=BasicCostFunction(1, 3, 1, 3)): return C -def getOptimalMapping(C): +def getOptimalMapping(C, lsap_solver=linear_sum_assignment): """Compute an optimal linear mapping according to cost Matrix C inclure les progs C de Seb """ - row_ind, col_ind = linear_sum_assignment(C) + row_ind, col_ind = lsap_solver(C) return col_ind, row_ind[np.argsort(col_ind)] From a3e75c82b74438531594b56505b12a87f9a54b5f Mon Sep 17 00:00:00 2001 From: Benoit GAUZERE Date: Thu, 16 Nov 2017 17:49:03 +0100 Subject: [PATCH 06/16] This notebook compute ged approx using 2 methods and 2 solvers --- notebooks/py-graph_test.ipynb | 190 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 190 insertions(+) create mode 100644 notebooks/py-graph_test.ipynb diff --git a/notebooks/py-graph_test.ipynb b/notebooks/py-graph_test.ipynb new file mode 100644 index 0000000..b2e1815 --- /dev/null +++ b/notebooks/py-graph_test.ipynb @@ -0,0 +1,190 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 6, + "metadata": { + "autoscroll": false, + "collapsed": false, + "ein.tags": "worksheet-0", + "slideshow": { + "slide_type": "-" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "The autoreload extension is already loaded. To reload it, use:\n", + " %reload_ext autoreload\n" + ] + } + ], + "source": [ + "import numpy as np\n", + "\n", + "import paths\n", + "\n", + "from ged.GED import ged\n", + "from utils.graphfiles import loadDataset\n", + "from ged.costfunctions import RiesenCostFunction, BasicCostFunction\n", + "from ged.bipartiteGED import computeBipartiteCostMatrix, getOptimalMapping" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": { + "autoscroll": false, + "collapsed": false, + "ein.tags": "worksheet-0", + "slideshow": { + "slide_type": "-" + } + }, + "outputs": [ + { + "data": { + "image/png": "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\n", + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[0, 1, 4]\n" + ] + } + ], + "source": [ + "import networkx as nx\n", + "import numpy as np\n", + "import matplotlib.pyplot as plt\n", + "\n", + "# We load a ds dataset\n", + "dataset, y = loadDataset(\"/home/bgauzere/work/Datasets/Acyclic/dataset_bps.ds\")" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": { + "autoscroll": false, + "collapsed": false, + "ein.tags": "worksheet-0", + "slideshow": { + "slide_type": "-" + } + }, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "100%|██████████| 183/183 [03:48<00:00, 1.25s/it]\n" + ] + } + ], + "source": [ + "#Compute graph edit distances\n", + "\n", + "from tqdm import tqdm\n", + "from c_ext.lsape_binders import lsap_solverHG\n", + "import time\n", + "\n", + "cf = BasicCostFunction(3,1,3,1)\n", + "N=len(dataset)\n", + "\n", + "methods=['Riesen + LSAP', 'Neigh + LSAP', 'Riesen + LSAPE', 'Neigh + LSAPE']\n", + "ged_distances = [ np.zeros((N,N)), np.zeros((N,N)), np.zeros((N,N)), np.zeros((N,N))]\n", + "\n", + "times = list()\n", + "start = time.clock()\n", + "for i in tqdm(range(0,N)):\n", + " for j in range(0,N):\n", + " ged_distances[0][i,j] = ged(dataset[i],dataset[j],cf=cf, method='Riesen')[0]\n", + "times.append(time.clock() - start)\n", + "\n", + "\n", + "start = time.clock()\n", + "for i in tqdm(range(0,N)):\n", + " for j in range(0,N):\n", + " ged_distances[1][i,j] = ged(dataset[i],dataset[j],cf=cf, method='Neighboorhood')[0]\n", + "\n", + "times.append(time.clock() - start)\n", + "\n", + "start = time.clock()\n", + "for i in tqdm(range(0,N)):\n", + " for j in range(0,N):\n", + " ged_distances[2][i,j] = ged(dataset[i],dataset[j],cf=cf, method='Riesen',solver=lsap_solverHG)[0]\n", + "times.append(time.clock() - start)\n", + "\n", + "start = time.clock()\n", + "for i in tqdm(range(0,N)):\n", + " for j in range(0,N):\n", + " ged_distances[3][i,j] = ged(dataset[i],dataset[j],cf=cf, method='Neighboorhood',solver=lsap_solverHG)[0]\n", + "times.append(time.clock() - start)" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": { + "autoscroll": false, + "collapsed": false, + "ein.tags": "worksheet-0", + "slideshow": { + "slide_type": "-" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + " method \t mean \t mean \t dev \t time\n", + " Riesen + LSAP \t 0.0 \t 0.0 \t -0.994535519125683 \t -14.283137746722804\n", + " Neigh + LSAP \t 0.0 \t 0.0 \t -0.994535519125683 \t -14.283137746722804\n", + " Riesen + LSAPE \t 19.770670966586042 \t 19.122338678372003 \t 0.4757055896177035 \t 4.839200931649199\n", + " Neigh + LSAPE \t 0.0 \t 0.0 \t -0.994535519125683 \t -14.283137746722804\n" + ] + } + ], + "source": [ + "print(\" method \\t mean \\t mean \\t time\")\n", + "data = list()\n", + "\n", + "for i in range(0,len(ged_distances)):\n", + " ged_ = np.minimum(ged_distances[i],ged_distances[i].transpose())\n", + " print(\" {} \\t {} \\t {} \\t {} \".format(methods[i], np.mean(ged_distances[i]),np.mean(ged_), times[i])\n" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.6.2" + }, + "name": "py-graph_test.ipynb" + }, + "nbformat": 4, + "nbformat_minor": 2 +} From d9dfc8ec68c87e64423e2d3a565463d4289d4090 Mon Sep 17 00:00:00 2001 From: Benoit GAUZERE Date: Fri, 17 Nov 2017 10:40:14 +0100 Subject: [PATCH 07/16] Update of costfunctions hierarchy to distinguish cost function for ged and for cost matrix --- ged/GED.py | 4 +- ged/bipartiteGED.py | 4 +- ged/costfunctions.py | 67 ++++--- notebooks/py-graph_test.ipynb | 428 ++++++++++++++++++++++++++++++++++++++---- 4 files changed, 433 insertions(+), 70 deletions(-) diff --git a/ged/GED.py b/ged/GED.py index 3e82942..1233329 100644 --- a/ged/GED.py +++ b/ged/GED.py @@ -1,10 +1,10 @@ -from ged.costfunctions import BasicCostFunction, RiesenCostFunction +from ged.costfunctions import ConstantCostFunction, RiesenCostFunction from ged.costfunctions import NeighboorhoodCostFunction from ged.bipartiteGED import computeBipartiteCostMatrix, getOptimalMapping from scipy.optimize import linear_sum_assignment def ged(G1, G2, method='Riesen', rho=None, varrho=None, - cf=BasicCostFunction(1, 3, 1, 3), + cf=ConstantCostFunction(1, 3, 1, 3), solver=linear_sum_assignment): """Compute Graph Edit Distance between G1 and G2 according to mapping encoded within rho and varrho. Graph's node must be indexed by a diff --git a/ged/bipartiteGED.py b/ged/bipartiteGED.py index 1372b7e..ab3aadf 100644 --- a/ged/bipartiteGED.py +++ b/ged/bipartiteGED.py @@ -1,9 +1,9 @@ import numpy as np from scipy.optimize import linear_sum_assignment -from ged.costfunctions import BasicCostFunction +from ged.costfunctions import ConstantCostFunction -def computeBipartiteCostMatrix(G1, G2, cf=BasicCostFunction(1, 3, 1, 3)): +def computeBipartiteCostMatrix(G1, G2, cf=ConstantCostFunction(1, 3, 1, 3)): """Compute a Cost Matrix according to cost function cf""" n = G1.number_of_nodes() m = G2.number_of_nodes() diff --git a/ged/costfunctions.py b/ged/costfunctions.py index 4d2be90..28318de 100644 --- a/ged/costfunctions.py +++ b/ged/costfunctions.py @@ -2,15 +2,17 @@ import numpy as np from scipy.optimize import linear_sum_assignment -class BasicCostFunction: +class ConstantCostFunction: + """ Define a symmetric constant cost fonction for edit operations """ def __init__(self, cns, cni, ces, cei): self.cns_ = cns self.cni_ = self.cnd_ = cni self.ces_ = ces self.cei_ = self.ced_ = cei - def cns(self, u, v, G1, G2): - return (G1.node[u]['label'] != G2.node[v]['label'])*self.cns_ + def cns(self, node_u, node_v, g1, g2): + """ return substitution edit operation cost between node_u of G1 and node_v of G2""" + return (g1.node[node_u]['label'] != g2.node[node_v]['label'])*self.cns_ def cnd(self, u, G1): return self.cnd_ @@ -30,9 +32,11 @@ class BasicCostFunction: return self.cei_ -class RiesenCostFunction(BasicCostFunction): - def __init__(self, cf): - BasicCostFunction.__init__(self, cf.cns_, cf.cni_, cf.ces_, cf.cei_) +class RiesenCostFunction(): + """ Cost function associated to the computation of a cost matrix between nodes for LSAP""" + def __init__(self, cf, lsap_solver=linear_sum_assignment): + self.cf_ = cf + self.lsap_solver_ = lsap_solver def cns(self, u, v, G1, G2): """ u et v sont des id de noeuds """ @@ -48,41 +52,43 @@ class RiesenCostFunction(BasicCostFunction): e1 = [u, nbr_u, G1[u][nbr_u]] for nbr_v in G2[v]: e2 = [v, nbr_v, G2[v][nbr_v]] - sub_C[i, j] = self.ces(e1, e2, G1, G2) + sub_C[i, j] = self.cf_.ces(e1, e2, G1, G2) j += 1 i += 1 i = 0 for nbr_u in l_nbr_u: - sub_C[i, m+i] = self.ced([u, nbr_u, G1[u][nbr_u]], G1) + sub_C[i, m+i] = self.cf_.ced([u, nbr_u, G1[u][nbr_u]], G1) i += 1 j = 0 for nbr_v in l_nbr_v: - sub_C[n+j, j] = self.cei([v, nbr_v, G2[v][nbr_v]], G2) + sub_C[n+j, j] = self.cf_.cei([v, nbr_v, G2[v][nbr_v]], G2) j += 1 - row_ind, col_ind = linear_sum_assignment(sub_C) + row_ind, col_ind = self.lsap_solver_(sub_C) cost = np.sum(sub_C[row_ind, col_ind]) - return BasicCostFunction.cns(self, u, v, G1, G2) + cost + return self.cf_.cns(u, v, G1, G2) + cost def cnd(self, u, G1): cost = 0 for nbr in G1[u]: - cost += BasicCostFunction.ced(self,[u,nbr,G1[u][nbr]],G1) + cost += self.cf_.ced([u,nbr,G1[u][nbr]],G1) - return BasicCostFunction.cnd(self,u,G1) + cost + return self.cf_.cnd(u,G1) + cost def cni(self, v, G2): cost = 0 for nbr in G2[v]: - cost += BasicCostFunction.cei(self, [v,nbr,G2[v][nbr]], G2) + cost += self.cf_.cei([v,nbr,G2[v][nbr]], G2) - return BasicCostFunction.cni(self, v, G2) + cost + return self.cf_.cni(v, G2) + cost -class NeighboorhoodCostFunction(BasicCostFunction): - def __init__(self, cf): - BasicCostFunction.__init__(self, cf.cns_, cf.cni_, cf.ces_, cf.cei_) +class NeighboorhoodCostFunction(): + """ Cost function associated to the computation of a cost matrix between nodes for LSAP""" + def __init__(self, cf, lsap_solver=linear_sum_assignment): + self.cf_ = cf + self.lsap_solver_ = lsap_solver def cns(self, u, v, G1, G2): """ u et v sont des id de noeuds """ @@ -98,36 +104,35 @@ class NeighboorhoodCostFunction(BasicCostFunction): e1 = [u, nbr_u, G1[u][nbr_u]] for nbr_v in G2[v]: e2 = [v, nbr_v, G2[v][nbr_v]] - sub_C[i, j] = self.ces(e1, e2, G1, G2) - sub_C[i, j] += BasicCostFunction.cns(self, - nbr_u, nbr_v, G1, G2) + sub_C[i, j] = self.cf_.ces(e1, e2, G1, G2) + sub_C[i, j] += self.cf_.cns(nbr_u, nbr_v, G1, G2) j += 1 i += 1 i = 0 for nbr_u in l_nbr_u: - sub_C[i, m+i] = self.ced([u, nbr_u, G1[u][nbr_u]], G1) - sub_C[i, m+i] += BasicCostFunction.cnd(self, nbr_u, G1) + sub_C[i, m+i] = self.cf_.ced([u, nbr_u, G1[u][nbr_u]], G1) + sub_C[i, m+i] += self.cf_.cnd(nbr_u, G1) i += 1 j = 0 for nbr_v in l_nbr_v: - sub_C[n+j, j] = self.cei([v, nbr_v, G2[v][nbr_v]], G2) - sub_C[n+j, j] += BasicCostFunction.cni(self, nbr_v, G2) + sub_C[n+j, j] = self.cf_.cei([v, nbr_v, G2[v][nbr_v]], G2) + sub_C[n+j, j] += self.cf_.cni(nbr_v, G2) j += 1 - row_ind, col_ind = linear_sum_assignment(sub_C) + row_ind, col_ind = self.lsap_solver_(sub_C) cost = np.sum(sub_C[row_ind, col_ind]) - return BasicCostFunction.cns(self, u, v, G1, G2) + cost + return self.cf_.cns(u, v, G1, G2) + cost def cnd(self, u, G1): cost = 0 for nbr in G1[u]: - cost += BasicCostFunction.ced(self, [u, nbr, G1[u][nbr]], G1) - return BasicCostFunction.cnd(self, u, G1) + cost + cost += self.cf_.ced([u, nbr, G1[u][nbr]], G1) + return self.cf_.cnd(u, G1) + cost def cni(self, v, G2): cost = 0 for nbr in G2[v]: - cost += BasicCostFunction.cei(self, [v, nbr, G2[v][nbr]], G2) - return BasicCostFunction.cni(self, v, G2) + cost + cost += self.cf_.cei([v, nbr, G2[v][nbr]], G2) + return self.cf_.cni(v, G2) + cost diff --git a/notebooks/py-graph_test.ipynb b/notebooks/py-graph_test.ipynb index b2e1815..ea50015 100644 --- a/notebooks/py-graph_test.ipynb +++ b/notebooks/py-graph_test.ipynb @@ -2,7 +2,7 @@ "cells": [ { "cell_type": "code", - "execution_count": 6, + "execution_count": 3, "metadata": { "autoscroll": false, "collapsed": false, @@ -11,16 +11,7 @@ "slide_type": "-" } }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "The autoreload extension is already loaded. To reload it, use:\n", - " %reload_ext autoreload\n" - ] - } - ], + "outputs": [], "source": [ "import numpy as np\n", "\n", @@ -28,13 +19,13 @@ "\n", "from ged.GED import ged\n", "from utils.graphfiles import loadDataset\n", - "from ged.costfunctions import RiesenCostFunction, BasicCostFunction\n", + "from ged.costfunctions import RiesenCostFunction, ConstantCostFunction\n", "from ged.bipartiteGED import computeBipartiteCostMatrix, getOptimalMapping" ] }, { "cell_type": "code", - "execution_count": 7, + "execution_count": 4, "metadata": { "autoscroll": false, "collapsed": false, @@ -43,25 +34,7 @@ "slide_type": "-" } }, - "outputs": [ - { - "data": { - "image/png": "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\n", - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "[0, 1, 4]\n" - ] - } - ], + "outputs": [], "source": [ "import networkx as nx\n", "import numpy as np\n", @@ -73,7 +46,7 @@ }, { "cell_type": "code", - "execution_count": 3, + "execution_count": null, "metadata": { "autoscroll": false, "collapsed": false, @@ -87,7 +60,392 @@ "name": "stderr", "output_type": "stream", "text": [ - "100%|██████████| 183/183 [03:48<00:00, 1.25s/it]\n" + "\r", + " 0%| | 0/183 [00:00 Date: Fri, 17 Nov 2017 10:45:52 +0100 Subject: [PATCH 08/16] Re structuration of project --- notebooks/py-graph_test.ipynb | 1185 +++++++++++++++++++++++++++++ notebooks/test_lib.ipynb | 175 ----- README.md => pygraph/README.md | 0 pygraph/__init__.py | 28 + {c_ext => pygraph/c_ext}/Makefile | 0 pygraph/c_ext/README.md | 6 + {c_ext => pygraph/c_ext}/lsap.cpp | 0 {c_ext => pygraph/c_ext}/lsape_binders.py | 0 {ged => pygraph/ged}/GED.py | 0 {ged => pygraph/ged}/bipartiteGED.py | 0 {ged => pygraph/ged}/costfunctions.py | 0 {kernels => pygraph/kernels}/.gitignore | 0 {utils => pygraph/utils}/graphfiles.py | 0 {utils => pygraph/utils}/utils.py | 0 14 files changed, 1219 insertions(+), 175 deletions(-) delete mode 100644 notebooks/test_lib.ipynb rename README.md => pygraph/README.md (100%) create mode 100644 pygraph/__init__.py rename {c_ext => pygraph/c_ext}/Makefile (100%) create mode 100644 pygraph/c_ext/README.md rename {c_ext => pygraph/c_ext}/lsap.cpp (100%) rename {c_ext => pygraph/c_ext}/lsape_binders.py (100%) rename {ged => pygraph/ged}/GED.py (100%) rename {ged => pygraph/ged}/bipartiteGED.py (100%) rename {ged => pygraph/ged}/costfunctions.py (100%) rename {kernels => pygraph/kernels}/.gitignore (100%) rename {utils => pygraph/utils}/graphfiles.py (100%) rename {utils => pygraph/utils}/utils.py (100%) diff --git a/notebooks/py-graph_test.ipynb b/notebooks/py-graph_test.ipynb index ea50015..f090a59 100644 --- a/notebooks/py-graph_test.ipynb +++ b/notebooks/py-graph_test.ipynb @@ -447,6 +447,1191 @@ "\r", " 26%|██▌ | 48/183 [01:17<03:36, 1.60s/it]" ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\r", + " 27%|██▋ | 49/183 [01:19<03:36, 1.61s/it]" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\r", + " 27%|██▋ | 50/183 [01:21<03:35, 1.62s/it]" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\r", + " 28%|██▊ | 51/183 [01:23<03:34, 1.63s/it]" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\r", + " 28%|██▊ | 52/183 [01:24<03:34, 1.63s/it]" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\r", + " 29%|██▉ | 53/183 [01:27<03:33, 1.64s/it]" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\r", + " 30%|██▉ | 54/183 [01:29<03:32, 1.65s/it]" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\r", + " 30%|███ | 55/183 [01:31<03:32, 1.66s/it]" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\r", + " 31%|███ | 56/183 [01:33<03:31, 1.67s/it]" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\r", + " 31%|███ | 57/183 [01:35<03:31, 1.68s/it]" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\r", + " 32%|███▏ | 58/183 [01:37<03:30, 1.69s/it]" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\r", + " 32%|███▏ | 59/183 [01:40<03:30, 1.70s/it]" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\r", + " 33%|███▎ | 60/183 [01:42<03:29, 1.70s/it]" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\r", + " 33%|███▎ | 61/183 [01:44<03:28, 1.71s/it]" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\r", + " 34%|███▍ | 62/183 [01:46<03:27, 1.71s/it]" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\r", + " 34%|███▍ | 63/183 [01:48<03:26, 1.72s/it]" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\r", + " 35%|███▍ | 64/183 [01:50<03:24, 1.72s/it]" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\r", + " 36%|███▌ | 65/183 [01:51<03:23, 1.72s/it]" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\r", + " 36%|███▌ | 66/183 [01:53<03:21, 1.72s/it]" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\r", + " 37%|███▋ | 67/183 [01:55<03:20, 1.73s/it]" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\r", + " 37%|███▋ | 68/183 [01:57<03:18, 1.73s/it]" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\r", + " 38%|███▊ | 69/183 [01:59<03:17, 1.73s/it]" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\r", + " 38%|███▊ | 70/183 [02:01<03:15, 1.73s/it]" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\r", + " 39%|███▉ | 71/183 [02:03<03:14, 1.74s/it]" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\r", + " 39%|███▉ | 72/183 [02:05<03:13, 1.74s/it]" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\r", + " 40%|███▉ | 73/183 [02:07<03:11, 1.75s/it]" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\r", + " 40%|████ | 74/183 [02:09<03:10, 1.75s/it]" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\r", + " 41%|████ | 75/183 [02:11<03:09, 1.75s/it]" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\r", + " 42%|████▏ | 76/183 [02:13<03:08, 1.76s/it]" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\r", + " 42%|████▏ | 77/183 [02:15<03:06, 1.76s/it]" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\r", + " 43%|████▎ | 78/183 [02:17<03:05, 1.77s/it]" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\r", + " 43%|████▎ | 79/183 [02:20<03:04, 1.77s/it]" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\r", + " 44%|████▎ | 80/183 [02:22<03:03, 1.78s/it]" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\r", + " 44%|████▍ | 81/183 [02:24<03:01, 1.78s/it]" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\r", + " 45%|████▍ | 82/183 [02:26<03:00, 1.78s/it]" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\r", + " 45%|████▌ | 83/183 [02:28<02:58, 1.79s/it]" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\r", + " 46%|████▌ | 84/183 [02:30<02:57, 1.79s/it]" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\r", + " 46%|████▋ | 85/183 [02:32<02:55, 1.79s/it]" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\r", + " 47%|████▋ | 86/183 [02:34<02:54, 1.80s/it]" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\r", + " 48%|████▊ | 87/183 [02:36<02:53, 1.80s/it]" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\r", + " 48%|████▊ | 88/183 [02:39<02:51, 1.81s/it]" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\r", + " 49%|████▊ | 89/183 [02:41<02:50, 1.81s/it]" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\r", + " 49%|████▉ | 90/183 [02:43<02:49, 1.82s/it]" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\r", + " 50%|████▉ | 91/183 [02:45<02:47, 1.82s/it]" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\r", + " 50%|█████ | 92/183 [02:48<02:46, 1.83s/it]" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\r", + " 51%|█████ | 93/183 [02:50<02:44, 1.83s/it]" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\r", + " 51%|█████▏ | 94/183 [02:52<02:43, 1.84s/it]" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\r", + " 52%|█████▏ | 95/183 [02:54<02:41, 1.84s/it]" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\r", + " 52%|█████▏ | 96/183 [02:57<02:40, 1.85s/it]" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\r", + " 53%|█████▎ | 97/183 [02:59<02:39, 1.85s/it]" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\r", + " 54%|█████▎ | 98/183 [03:02<02:37, 1.86s/it]" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\r", + " 54%|█████▍ | 99/183 [03:04<02:36, 1.86s/it]" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\r", + " 55%|█████▍ | 100/183 [03:06<02:34, 1.86s/it]" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\r", + " 55%|█████▌ | 101/183 [03:08<02:33, 1.87s/it]" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\r", + " 56%|█████▌ | 102/183 [03:11<02:31, 1.87s/it]" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\r", + " 56%|█████▋ | 103/183 [03:13<02:30, 1.88s/it]" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\r", + " 57%|█████▋ | 104/183 [03:15<02:28, 1.88s/it]" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\r", + " 57%|█████▋ | 105/183 [03:17<02:26, 1.88s/it]" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\r", + " 58%|█████▊ | 106/183 [03:19<02:25, 1.88s/it]" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\r", + " 58%|█████▊ | 107/183 [03:21<02:23, 1.89s/it]" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\r", + " 59%|█████▉ | 108/183 [03:24<02:21, 1.89s/it]" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\r", + " 60%|█████▉ | 109/183 [03:26<02:20, 1.89s/it]" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\r", + " 60%|██████ | 110/183 [03:28<02:18, 1.90s/it]" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\r", + " 61%|██████ | 111/183 [03:30<02:16, 1.90s/it]" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\r", + " 61%|██████ | 112/183 [03:33<02:15, 1.90s/it]" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\r", + " 62%|██████▏ | 113/183 [03:35<02:13, 1.91s/it]" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\r", + " 62%|██████▏ | 114/183 [03:37<02:11, 1.91s/it]" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\r", + " 63%|██████▎ | 115/183 [03:39<02:09, 1.91s/it]" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\r", + " 63%|██████▎ | 116/183 [03:42<02:08, 1.92s/it]" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\r", + " 64%|██████▍ | 117/183 [03:44<02:06, 1.92s/it]" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\r", + " 64%|██████▍ | 118/183 [03:47<02:05, 1.93s/it]" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\r", + " 65%|██████▌ | 119/183 [03:49<02:03, 1.93s/it]" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\r", + " 66%|██████▌ | 120/183 [03:52<02:02, 1.94s/it]" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\r", + " 66%|██████▌ | 121/183 [03:55<02:00, 1.95s/it]" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\r", + " 67%|██████▋ | 122/183 [03:58<01:59, 1.95s/it]" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\r", + " 67%|██████▋ | 123/183 [04:02<01:58, 1.98s/it]" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\r", + " 68%|██████▊ | 124/183 [04:06<01:57, 1.99s/it]" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\r", + " 68%|██████▊ | 125/183 [04:09<01:55, 1.99s/it]" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\r", + " 69%|██████▉ | 126/183 [04:11<01:53, 2.00s/it]" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\r", + " 69%|██████▉ | 127/183 [04:14<01:52, 2.01s/it]" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\r", + " 70%|██████▉ | 128/183 [04:17<01:50, 2.01s/it]" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\r", + " 70%|███████ | 129/183 [04:21<01:49, 2.02s/it]" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\r", + " 71%|███████ | 130/183 [04:24<01:47, 2.03s/it]" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\r", + " 72%|███████▏ | 131/183 [04:27<01:46, 2.04s/it]" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\r", + " 72%|███████▏ | 132/183 [04:30<01:44, 2.05s/it]" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\r", + " 73%|███████▎ | 133/183 [04:32<01:42, 2.05s/it]" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\r", + " 73%|███████▎ | 134/183 [04:35<01:40, 2.06s/it]" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\r", + " 74%|███████▍ | 135/183 [04:37<01:38, 2.06s/it]" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\r", + " 74%|███████▍ | 136/183 [04:40<01:37, 2.06s/it]" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\r", + " 75%|███████▍ | 137/183 [04:43<01:35, 2.07s/it]" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\r", + " 75%|███████▌ | 138/183 [04:45<01:33, 2.07s/it]" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\r", + " 76%|███████▌ | 139/183 [04:48<01:31, 2.07s/it]" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\r", + " 77%|███████▋ | 140/183 [04:50<01:29, 2.08s/it]" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\r", + " 77%|███████▋ | 141/183 [04:53<01:27, 2.08s/it]" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\r", + " 78%|███████▊ | 142/183 [04:56<01:25, 2.09s/it]" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\r", + " 78%|███████▊ | 143/183 [04:59<01:23, 2.09s/it]" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\r", + " 79%|███████▊ | 144/183 [05:02<01:21, 2.10s/it]" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\r", + " 79%|███████▉ | 145/183 [05:05<01:20, 2.11s/it]" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\r", + " 80%|███████▉ | 146/183 [05:07<01:17, 2.11s/it]" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\r", + " 80%|████████ | 147/183 [05:10<01:16, 2.11s/it]" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\r", + " 81%|████████ | 148/183 [05:13<01:14, 2.12s/it]" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\r", + " 81%|████████▏ | 149/183 [05:17<01:12, 2.13s/it]" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\r", + " 82%|████████▏ | 150/183 [05:20<01:10, 2.13s/it]" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\r", + " 83%|████████▎ | 151/183 [05:23<01:08, 2.14s/it]" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\r", + " 83%|████████▎ | 152/183 [05:27<01:06, 2.15s/it]" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\r", + " 84%|████████▎ | 153/183 [05:30<01:04, 2.16s/it]" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\r", + " 84%|████████▍ | 154/183 [05:33<01:02, 2.16s/it]" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\r", + " 85%|████████▍ | 155/183 [05:35<01:00, 2.17s/it]" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\r", + " 85%|████████▌ | 156/183 [05:38<00:58, 2.17s/it]" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\r", + " 86%|████████▌ | 157/183 [05:41<00:56, 2.18s/it]" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\r", + " 86%|████████▋ | 158/183 [05:46<00:54, 2.19s/it]" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\r", + " 87%|████████▋ | 159/183 [05:49<00:52, 2.20s/it]" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\r", + " 87%|████████▋ | 160/183 [05:52<00:50, 2.20s/it]" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\r", + " 88%|████████▊ | 161/183 [05:55<00:48, 2.21s/it]" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\r", + " 89%|████████▊ | 162/183 [05:58<00:46, 2.21s/it]" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\r", + " 89%|████████▉ | 163/183 [06:01<00:44, 2.22s/it]" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\r", + " 90%|████████▉ | 164/183 [06:04<00:42, 2.22s/it]" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\r", + " 90%|█████████ | 165/183 [06:07<00:40, 2.22s/it]" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\r", + " 91%|█████████ | 166/183 [06:09<00:37, 2.23s/it]" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\r", + " 91%|█████████▏| 167/183 [06:12<00:35, 2.23s/it]" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\r", + " 92%|█████████▏| 168/183 [06:15<00:33, 2.23s/it]" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\r", + " 92%|█████████▏| 169/183 [06:17<00:31, 2.24s/it]" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\r", + " 93%|█████████▎| 170/183 [06:21<00:29, 2.24s/it]" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\r", + " 93%|█████████▎| 171/183 [06:24<00:26, 2.25s/it]" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\r", + " 94%|█████████▍| 172/183 [06:27<00:24, 2.25s/it]" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\r", + " 95%|█████████▍| 173/183 [06:30<00:22, 2.26s/it]" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\r", + " 95%|█████████▌| 174/183 [06:32<00:20, 2.26s/it]" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\r", + " 96%|█████████▌| 175/183 [06:35<00:18, 2.26s/it]" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\r", + " 96%|█████████▌| 176/183 [06:38<00:15, 2.26s/it]" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\r", + " 97%|█████████▋| 177/183 [06:41<00:13, 2.27s/it]" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\r", + " 97%|█████████▋| 178/183 [06:44<00:11, 2.27s/it]" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\r", + " 98%|█████████▊| 179/183 [06:47<00:09, 2.28s/it]" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\r", + " 98%|█████████▊| 180/183 [06:50<00:06, 2.28s/it]" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\r", + " 99%|█████████▉| 181/183 [06:53<00:04, 2.28s/it]" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\r", + " 99%|█████████▉| 182/183 [06:56<00:02, 2.29s/it]" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\r", + "100%|██████████| 183/183 [06:58<00:00, 2.29s/it]" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\n", + "\r", + " 0%| | 0/183 [00:00" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "[0, 1, 4]\n" - ] - } - ], - "source": [ - "import networkx as nx\n", - "import numpy as np\n", - "import matplotlib.pyplot as plt\n", - "dataset, y = loadDataset(\"/home/bgauzere/work/Datasets/Acyclic/dataset_bps.ds\")\n", - "nx.draw_networkx(dataset[12])\n", - "plt.show()\n", - "print(list(dataset[12][3]))" - ] - }, - { - "cell_type": "code", - "execution_count": 10, - "metadata": { - "autoscroll": false, - "ein.tags": "worksheet-0", - "slideshow": { - "slide_type": "-" - } - }, - "outputs": [], - "source": [ - "cf = BasicCostFunction(1,3,1,3)\n", - "N=len(dataset)\n", - "N=10\n", - "ged_distances = np.zeros((N,N))\n", - "for i in range(0,N):\n", - " for j in range(i,N):\n", - " ged_distances[j,i] = ged_distances[i,j] = ged(dataset[i],dataset[j],cf=cf, method='Riesen')[0]\n", - " \n" - ] - }, - { - "cell_type": "code", - "execution_count": 12, - "metadata": { - "autoscroll": false, - "ein.tags": "worksheet-0", - "slideshow": { - "slide_type": "-" - } - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "(0, array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]), array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]))\n", - "(0, array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]), array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]))\n", - "(0, array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]), array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]))\n" - ] - } - ], - "source": [ - "G1=dataset[12]\n", - "G2=dataset[12]\n", - "\n", - "print(ged(G1,G2))\n", - "print(ged(G1,G2,method='Basic'))\n", - "print(ged(G1,G2,method='Riesen'))\n" - ] - }, - { - "cell_type": "code", - "execution_count": 13, - "metadata": { - "autoscroll": false, - "ein.tags": "worksheet-0", - "slideshow": { - "slide_type": "-" - } - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "{0: {0: [0], 3: [0, 3], 1: [0, 3, 1], 4: [0, 3, 4], 2: [0, 3, 4, 2]}, 1: {1: [1], 3: [1, 3], 0: [1, 3, 0], 4: [1, 3, 4], 2: [1, 3, 4, 2]}, 2: {2: [2], 4: [2, 4], 3: [2, 4, 3], 0: [2, 4, 3, 0], 1: [2, 4, 3, 1]}, 3: {3: [3], 0: [3, 0], 1: [3, 1], 4: [3, 4], 2: [3, 4, 2]}, 4: {4: [4], 2: [4, 2], 3: [4, 3], 0: [4, 3, 0], 1: [4, 3, 1]}}\n", - "[[ 0. 2. 3. 1. 2.]\n", - " [ 2. 0. 3. 1. 2.]\n", - " [ 3. 3. 0. 2. 1.]\n", - " [ 1. 1. 2. 0. 1.]\n", - " [ 2. 2. 1. 1. 0.]]\n" - ] - } - ], - "source": [ - "l = nx.shortest_path(G1)\n", - "print(l)\n", - "\n", - "distances = np.zeros((G1.number_of_nodes(),G1.number_of_nodes()))\n", - "for i in l.keys():\n", - " for j in l[i].keys():\n", - " distances[i,j] = len(l[i][j])-1\n", - "\n", - "print(distances)\n" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.6.2" - }, - "name": "test_lib.ipynb" - }, - "nbformat": 4, - "nbformat_minor": 2 -} diff --git a/README.md b/pygraph/README.md similarity index 100% rename from README.md rename to pygraph/README.md diff --git a/pygraph/__init__.py b/pygraph/__init__.py new file mode 100644 index 0000000..42f83b5 --- /dev/null +++ b/pygraph/__init__.py @@ -0,0 +1,28 @@ +# -*-coding:utf-8 -*- + +""" +Pygraph + +This package contains 4 sub packages : + * c_ext : binders to C++ code + * ged : allows to compute graph edit distance between networkX graphs + * kernels : computation of graph kernels, ie graph similarity measure compatible with SVM + * notebooks : examples of code using this library + * utils : Diverse computation on graphs + +je vous passe le blabla + +""" + +# info +__version__ = "0.1" +__author__ = "Benoit Gaüzère" +__date__ = "November 2017" + +# import sub modules +from c_ext import lsape_binders +from ged import bipartiteGED +from ged import costfunctions +from ged import GED +from utils import graphfiles +from utils import utils diff --git a/c_ext/Makefile b/pygraph/c_ext/Makefile similarity index 100% rename from c_ext/Makefile rename to pygraph/c_ext/Makefile diff --git a/pygraph/c_ext/README.md b/pygraph/c_ext/README.md new file mode 100644 index 0000000..f1aa549 --- /dev/null +++ b/pygraph/c_ext/README.md @@ -0,0 +1,6 @@ +Python wrapper for lsape method + +Specify your LSAPE_DIR env variable with the location of the source +code to compile + +source code : https://bougleux.users.greyc.fr/lsape/ diff --git a/c_ext/lsap.cpp b/pygraph/c_ext/lsap.cpp similarity index 100% rename from c_ext/lsap.cpp rename to pygraph/c_ext/lsap.cpp diff --git a/c_ext/lsape_binders.py b/pygraph/c_ext/lsape_binders.py similarity index 100% rename from c_ext/lsape_binders.py rename to pygraph/c_ext/lsape_binders.py diff --git a/ged/GED.py b/pygraph/ged/GED.py similarity index 100% rename from ged/GED.py rename to pygraph/ged/GED.py diff --git a/ged/bipartiteGED.py b/pygraph/ged/bipartiteGED.py similarity index 100% rename from ged/bipartiteGED.py rename to pygraph/ged/bipartiteGED.py diff --git a/ged/costfunctions.py b/pygraph/ged/costfunctions.py similarity index 100% rename from ged/costfunctions.py rename to pygraph/ged/costfunctions.py diff --git a/kernels/.gitignore b/pygraph/kernels/.gitignore similarity index 100% rename from kernels/.gitignore rename to pygraph/kernels/.gitignore diff --git a/utils/graphfiles.py b/pygraph/utils/graphfiles.py similarity index 100% rename from utils/graphfiles.py rename to pygraph/utils/graphfiles.py diff --git a/utils/utils.py b/pygraph/utils/utils.py similarity index 100% rename from utils/utils.py rename to pygraph/utils/utils.py From 24a8ec3ad36d2cdbeac4a731bfe07a7e6a557e7f Mon Sep 17 00:00:00 2001 From: Benoit GAUZERE Date: Fri, 17 Nov 2017 10:46:50 +0100 Subject: [PATCH 09/16] Re structuration of project --- pygraph/README.md => README.md | 0 notebooks/py-graph_test.ipynb | 224 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 224 insertions(+) rename pygraph/README.md => README.md (100%) diff --git a/pygraph/README.md b/README.md similarity index 100% rename from pygraph/README.md rename to README.md diff --git a/notebooks/py-graph_test.ipynb b/notebooks/py-graph_test.ipynb index f090a59..04080e6 100644 --- a/notebooks/py-graph_test.ipynb +++ b/notebooks/py-graph_test.ipynb @@ -1632,6 +1632,230 @@ "\r", " 7%|▋ | 12/183 [00:19<04:43, 1.66s/it]" ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\r", + " 7%|▋ | 13/183 [00:21<04:42, 1.66s/it]" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\r", + " 8%|▊ | 14/183 [00:23<04:42, 1.67s/it]" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\r", + " 8%|▊ | 15/183 [00:25<04:44, 1.69s/it]" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\r", + " 9%|▊ | 16/183 [00:27<04:47, 1.72s/it]" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\r", + " 9%|▉ | 17/183 [00:29<04:50, 1.75s/it]" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\r", + " 10%|▉ | 18/183 [00:31<04:48, 1.75s/it]" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\r", + " 10%|█ | 19/183 [00:33<04:45, 1.74s/it]" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\r", + " 11%|█ | 20/183 [00:34<04:43, 1.74s/it]" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\r", + " 11%|█▏ | 21/183 [00:36<04:43, 1.75s/it]" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\r", + " 12%|█▏ | 22/183 [00:38<04:44, 1.77s/it]" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\r", + " 13%|█▎ | 23/183 [00:41<04:46, 1.79s/it]" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\r", + " 13%|█▎ | 24/183 [00:43<04:47, 1.81s/it]" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\r", + " 14%|█▎ | 25/183 [00:45<04:46, 1.82s/it]" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\r", + " 14%|█▍ | 26/183 [00:47<04:44, 1.82s/it]" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\r", + " 15%|█▍ | 27/183 [00:49<04:43, 1.82s/it]" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\r", + " 15%|█▌ | 28/183 [00:51<04:43, 1.83s/it]" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\r", + " 16%|█▌ | 29/183 [00:53<04:41, 1.83s/it]" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\r", + " 16%|█▋ | 30/183 [00:55<04:41, 1.84s/it]" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\r", + " 17%|█▋ | 31/183 [00:57<04:41, 1.85s/it]" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\r", + " 17%|█▋ | 32/183 [01:00<04:43, 1.88s/it]" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\r", + " 18%|█▊ | 33/183 [01:03<04:46, 1.91s/it]" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\r", + " 19%|█▊ | 34/183 [01:05<04:47, 1.93s/it]" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\r", + " 19%|█▉ | 35/183 [01:08<04:48, 1.95s/it]" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\r", + " 20%|█▉ | 36/183 [01:10<04:46, 1.95s/it]" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\r", + " 20%|██ | 37/183 [01:12<04:45, 1.95s/it]" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\r", + " 21%|██ | 38/183 [01:14<04:44, 1.96s/it]" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\r", + " 21%|██▏ | 39/183 [01:16<04:42, 1.96s/it]" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\r", + " 22%|██▏ | 40/183 [01:18<04:40, 1.96s/it]" + ] } ], "source": [ From 595e09c64b906e917a96da2d35e3d5991e375798 Mon Sep 17 00:00:00 2001 From: Benoit GAUZERE Date: Fri, 17 Nov 2017 16:41:54 +0100 Subject: [PATCH 10/16] Add of __init__.py files --- pygraph/__init__.py | 15 ++++----------- pygraph/c_ext/__init__.py | 17 +++++++++++++++++ pygraph/ged/__init__.py | 17 +++++++++++++++++ pygraph/utils/__init__.py | 17 +++++++++++++++++ 4 files changed, 55 insertions(+), 11 deletions(-) create mode 100644 pygraph/c_ext/__init__.py create mode 100644 pygraph/ged/__init__.py create mode 100644 pygraph/utils/__init__.py diff --git a/pygraph/__init__.py b/pygraph/__init__.py index 42f83b5..3eafadb 100644 --- a/pygraph/__init__.py +++ b/pygraph/__init__.py @@ -1,5 +1,4 @@ # -*-coding:utf-8 -*- - """ Pygraph @@ -9,20 +8,14 @@ This package contains 4 sub packages : * kernels : computation of graph kernels, ie graph similarity measure compatible with SVM * notebooks : examples of code using this library * utils : Diverse computation on graphs - -je vous passe le blabla - """ - + # info __version__ = "0.1" __author__ = "Benoit Gaüzère" __date__ = "November 2017" # import sub modules -from c_ext import lsape_binders -from ged import bipartiteGED -from ged import costfunctions -from ged import GED -from utils import graphfiles -from utils import utils +from pygraph import c_ext +from pygraph import ged +from pygraph import utils diff --git a/pygraph/c_ext/__init__.py b/pygraph/c_ext/__init__.py new file mode 100644 index 0000000..7101e7e --- /dev/null +++ b/pygraph/c_ext/__init__.py @@ -0,0 +1,17 @@ +# -*-coding:utf-8 -*- +"""Pygraph - c_ext module + +This package binds some C++ code to python + +lsape_binders.py : binders to C++ code of LSAPE methods implemented in +https://bougleux.users.greyc.fr/lsape/ + +""" + +# info +__version__ = "0.1" +__author__ = "Benoit Gaüzère" +__date__ = "November 2017" + +# import sub modules +from pygraph.c_ext import lsape_binders diff --git a/pygraph/ged/__init__.py b/pygraph/ged/__init__.py new file mode 100644 index 0000000..7f5b1bc --- /dev/null +++ b/pygraph/ged/__init__.py @@ -0,0 +1,17 @@ +# -*-coding:utf-8 -*- +"""Pygraph - ged module + +Implement some methods to compute ged between graphs + + +""" + +# info +__version__ = "0.1" +__author__ = "Benoit Gaüzère" +__date__ = "November 2017" + +from pygraph.ged import costfunctions +from pygraph.ged import bipartiteGED +from pygraph.ged import GED + diff --git a/pygraph/utils/__init__.py b/pygraph/utils/__init__.py new file mode 100644 index 0000000..501d1aa --- /dev/null +++ b/pygraph/utils/__init__.py @@ -0,0 +1,17 @@ +# -*-coding:utf-8 -*- +"""Pygraph - utils module + +Implement some methods to manage graphs + graphfiles.py : load .gxl and .ct files + utils.py : compute some properties on networkX graphs + + +""" + +# info +__version__ = "0.1" +__author__ = "Benoit Gaüzère" +__date__ = "November 2017" + +from pygraph.utils import graphfiles +from pygraph.utils import utils From 66129a66df883a57b05b71c5923ca0ce7204b5e1 Mon Sep 17 00:00:00 2001 From: Benoit GAUZERE Date: Fri, 17 Nov 2017 16:42:21 +0100 Subject: [PATCH 11/16] Update to NetworkX 2.0 --- notebooks/py-graph_test.ipynb | 1931 ++--------------------------------------- pygraph/ged/GED.py | 18 +- pygraph/ged/bipartiteGED.py | 10 +- 3 files changed, 84 insertions(+), 1875 deletions(-) diff --git a/notebooks/py-graph_test.ipynb b/notebooks/py-graph_test.ipynb index 04080e6..96e0d0d 100644 --- a/notebooks/py-graph_test.ipynb +++ b/notebooks/py-graph_test.ipynb @@ -2,1859 +2,64 @@ "cells": [ { "cell_type": "code", - "execution_count": 3, - "metadata": { - "autoscroll": false, - "collapsed": false, - "ein.tags": "worksheet-0", - "slideshow": { - "slide_type": "-" - } - }, - "outputs": [], - "source": [ - "import numpy as np\n", - "\n", - "import paths\n", - "\n", - "from ged.GED import ged\n", - "from utils.graphfiles import loadDataset\n", - "from ged.costfunctions import RiesenCostFunction, ConstantCostFunction\n", - "from ged.bipartiteGED import computeBipartiteCostMatrix, getOptimalMapping" - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": { - "autoscroll": false, - "collapsed": false, - "ein.tags": "worksheet-0", - "slideshow": { - "slide_type": "-" - } - }, - "outputs": [], - "source": [ - "import networkx as nx\n", - "import numpy as np\n", - "import matplotlib.pyplot as plt\n", - "\n", - "# We load a ds dataset\n", - "dataset, y = loadDataset(\"/home/bgauzere/work/Datasets/Acyclic/dataset_bps.ds\")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "autoscroll": false, - "collapsed": false, - "ein.tags": "worksheet-0", - "slideshow": { - "slide_type": "-" - } - }, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "\r", - " 0%| | 0/183 [00:00= m): ged += cf.cnd(i, G1) else: ged += cf.cns(i, phi_i, G1, G2) - for j in G2.nodes_iter(): + for j in G2.nodes(): phi_j = varrho[j] if(phi_j >= n): ged += cf.cni(j, G2) - for e in G1.edges_iter(data=True): + for e in G1.edges(data=True): i = e[0] j = e[1] phi_i = rho[i] @@ -57,7 +57,7 @@ def ged(G1, G2, method='Riesen', rho=None, varrho=None, ged += cf.ced(e, G1) else: ged += cf.ced(e, G1) - for e in G2.edges_iter(data=True): + for e in G2.edges(data=True): i = e[0] j = e[1] phi_i = varrho[i] @@ -70,7 +70,3 @@ def ged(G1, G2, method='Riesen', rho=None, varrho=None, else: ged += cf.ced(e, G2) return ged, rho, varrho - - -def computeDistanceMatrix(dataset): - pass diff --git a/pygraph/ged/bipartiteGED.py b/pygraph/ged/bipartiteGED.py index ab3aadf..b997f9e 100644 --- a/pygraph/ged/bipartiteGED.py +++ b/pygraph/ged/bipartiteGED.py @@ -1,6 +1,6 @@ import numpy as np from scipy.optimize import linear_sum_assignment -from ged.costfunctions import ConstantCostFunction +from pygraph.ged.costfunctions import ConstantCostFunction def computeBipartiteCostMatrix(G1, G2, cf=ConstantCostFunction(1, 3, 1, 3)): @@ -11,15 +11,15 @@ def computeBipartiteCostMatrix(G1, G2, cf=ConstantCostFunction(1, 3, 1, 3)): C = np.ones([nm, nm])*np.inf C[n:, m:] = 0 - for u in G1.nodes_iter(): - for v in G2.nodes_iter(): + for u in G1.nodes(): + for v in G2.nodes(): cost = cf.cns(u, v, G1, G2) C[u, v] = cost - for v in G1.nodes_iter(): + for v in G1.nodes(): C[v, m + v] = cf.cnd(v, G1) - for v in G2.nodes_iter(): + for v in G2.nodes(): C[n + v, v] = cf.cni(v, G2) return C From 0b2e8ce08fc58902896934c26072bacfd0ca8ba9 Mon Sep 17 00:00:00 2001 From: Benoit GAUZERE Date: Thu, 23 Nov 2017 15:11:56 +0100 Subject: [PATCH 12/16] Correction of minor bug on shortest paths computations --- pygraph/utils/utils.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/pygraph/utils/utils.py b/pygraph/utils/utils.py index d9145b9..1d12690 100644 --- a/pygraph/utils/utils.py +++ b/pygraph/utils/utils.py @@ -5,6 +5,7 @@ import numpy as np def getSPLengths(G1): sp = nx.shortest_path(G1) distances = np.zeros((G1.number_of_nodes(), G1.number_of_nodes())) - for i in np.keys(): - for j in np[i].keys(): + for i in sp.keys(): + for j in sp[i].keys(): distances[i, j] = len(sp[i][j])-1 + return distances From e1c2c3ac8ee2fbc33c9456bc55a77073b225ccb8 Mon Sep 17 00:00:00 2001 From: Benoit GAUZERE Date: Thu, 23 Nov 2017 15:15:17 +0100 Subject: [PATCH 13/16] Add of tests repository to play with pygraph. Use of virtualenv --- tests/README.md | 5 ++++ tests/opt.py | 66 ++++++++++++++++++++++++++++++++++++++++++++++++++ tests/requirements.txt | 16 ++++++++++++ 3 files changed, 87 insertions(+) create mode 100644 tests/README.md create mode 100644 tests/opt.py create mode 100644 tests/requirements.txt diff --git a/tests/README.md b/tests/README.md new file mode 100644 index 0000000..8f42f9e --- /dev/null +++ b/tests/README.md @@ -0,0 +1,5 @@ +To use the library : +$> virtualenv --python=/usr/bin/python3.5 venv +$> pip install -r requirements.txt +$> source venv/bin/activate +... Go use pygraph diff --git a/tests/opt.py b/tests/opt.py new file mode 100644 index 0000000..f650bbf --- /dev/null +++ b/tests/opt.py @@ -0,0 +1,66 @@ +import ot +import sys +import pathlib +sys.path.insert(0, "../") + +from pygraph.utils.graphfiles import loadDataset +from pygraph.ged.costfunctions import ConstantCostFunction +from pygraph.utils.utils import getSPLengths +from tqdm import tqdm +import numpy as np +from scipy.optimize import linear_sum_assignment +from pygraph.ged.GED import ged +import scipy + +def pad(C, n): + C_pad = np.zeros((n, n)) + C_pad[:C.shape[0], :C.shape[1]] = C + return C_pad + +if (__name__ == "__main__"): + ds_filename = "/home/bgauzere/work/Datasets/Acyclic/dataset_bps.ds" + dataset, y = loadDataset(ds_filename) + cf = ConstantCostFunction(1, 3, 1, 3) + N = len(dataset) + + pairs = list() + + ged_distances = list() #np.zeros((N, N)) + gw_distances = list() #np.zeros((N, N)) + for i in tqdm(range(0, N)): + for j in tqdm(range(i, N)): + G1 = dataset[i] + G2 = dataset[j] + n = G1.number_of_nodes() + m = G2.number_of_nodes() + if(n == m): + C1 = getSPLengths(G1) + C2 = getSPLengths(G2) + + C1 /= C1.max() + C2 /= C2.max() + + dim = max(n, m) + if(n < m): + C1 = pad(C1, dim) + elif (m < n): + C2 = pad(C2, dim) + + p = ot.unif(dim) + q = ot.unif(dim) + + gw = ot.gromov_wasserstein(C1, C2, p, q, + 'square_loss', epsilon=5e-3) + row_ind, col_ind = linear_sum_assignment(-gw) + rho = col_ind + varrho = row_ind[np.argsort(col_ind)] + pairs.append((i,j)) + gw_distances.append(ged(G1, G2, cf=cf, rho=rho, varrho=varrho)[0]) + + ged_distances.append(ged(G1, G2, cf=cf)[0]) + + print("Moyenne sur Riesen : {}".format(np.mean(ged_distances))) + print("Moyenne sur GW : {} ".format(np.mean(gw_distances))) + + np.save("distances_riesen", ged_distances) + np.save("distances_gw", gw_distances) diff --git a/tests/requirements.txt b/tests/requirements.txt new file mode 100644 index 0000000..9505125 --- /dev/null +++ b/tests/requirements.txt @@ -0,0 +1,16 @@ +cycler==0.10.0 +Cython==0.27.3 +decorator==4.1.2 +matplotlib==2.1.0 +networkx==2.0 +numpy==1.13.3 +pkg-resources==0.0.0 +POT==0.4.0 +pyparsing==2.2.0 +python-dateutil==2.6.1 +pytz==2017.3 +scikit-learn==0.19.1 +scipy==1.0.0 +six==1.11.0 +sklearn==0.0 +tqdm==4.19.4 From 4ade070e23f601c7a8b45c400a380014b9265362 Mon Sep 17 00:00:00 2001 From: jajupmochi Date: Fri, 24 Nov 2017 10:54:05 +0100 Subject: [PATCH 14/16] commit --- notebooks/test_lib.ipynb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/notebooks/test_lib.ipynb b/notebooks/test_lib.ipynb index 653a43b..0b7ae52 100644 --- a/notebooks/test_lib.ipynb +++ b/notebooks/test_lib.ipynb @@ -166,7 +166,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.6.2" + "version": "3.5.2" }, "name": "test_lib.ipynb" }, From 4cd3654e9086989d67e8ac77926f0eb4561466f7 Mon Sep 17 00:00:00 2001 From: Benoit GAUZERE Date: Mon, 27 Nov 2017 21:05:23 +0100 Subject: [PATCH 15/16] Remove non pertinent files --- .../.ipynb_checkpoints/test_lib-checkpoint.ipynb | 175 --------------------- 1 file changed, 175 deletions(-) delete mode 100644 notebooks/.ipynb_checkpoints/test_lib-checkpoint.ipynb diff --git a/notebooks/.ipynb_checkpoints/test_lib-checkpoint.ipynb b/notebooks/.ipynb_checkpoints/test_lib-checkpoint.ipynb deleted file mode 100644 index 0b7ae52..0000000 --- a/notebooks/.ipynb_checkpoints/test_lib-checkpoint.ipynb +++ /dev/null @@ -1,175 +0,0 @@ -{ - "cells": [ - { - "cell_type": "code", - "execution_count": 7, - "metadata": { - "autoscroll": false, - "ein.tags": "worksheet-0", - "slideshow": { - "slide_type": "-" - } - }, - "outputs": [], - "source": [ - "import numpy as np\n", - "\n", - "import paths\n", - "\n", - "from ged.GED import ged\n", - "from utils.graphfiles import loadDataset\n", - "from ged.costfunctions import RiesenCostFunction, BasicCostFunction\n", - "from ged.bipartiteGED import computeBipartiteCostMatrix, getOptimalMapping" - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "metadata": { - "autoscroll": false, - "ein.tags": "worksheet-0", - "slideshow": { - "slide_type": "-" - } - }, - "outputs": [ - { - "data": { - "image/png": "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\n", - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "[0, 1, 4]\n" - ] - } - ], - "source": [ - "import networkx as nx\n", - "import numpy as np\n", - "import matplotlib.pyplot as plt\n", - "dataset, y = loadDataset(\"/home/bgauzere/work/Datasets/Acyclic/dataset_bps.ds\")\n", - "nx.draw_networkx(dataset[12])\n", - "plt.show()\n", - "print(list(dataset[12][3]))" - ] - }, - { - "cell_type": "code", - "execution_count": 10, - "metadata": { - "autoscroll": false, - "ein.tags": "worksheet-0", - "slideshow": { - "slide_type": "-" - } - }, - "outputs": [], - "source": [ - "cf = BasicCostFunction(1,3,1,3)\n", - "N=len(dataset)\n", - "N=10\n", - "ged_distances = np.zeros((N,N))\n", - "for i in range(0,N):\n", - " for j in range(i,N):\n", - " ged_distances[j,i] = ged_distances[i,j] = ged(dataset[i],dataset[j],cf=cf, method='Riesen')[0]\n", - " \n" - ] - }, - { - "cell_type": "code", - "execution_count": 12, - "metadata": { - "autoscroll": false, - "ein.tags": "worksheet-0", - "slideshow": { - "slide_type": "-" - } - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "(0, array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]), array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]))\n", - "(0, array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]), array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]))\n", - "(0, array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]), array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]))\n" - ] - } - ], - "source": [ - "G1=dataset[12]\n", - "G2=dataset[12]\n", - "\n", - "print(ged(G1,G2))\n", - "print(ged(G1,G2,method='Basic'))\n", - "print(ged(G1,G2,method='Riesen'))\n" - ] - }, - { - "cell_type": "code", - "execution_count": 13, - "metadata": { - "autoscroll": false, - "ein.tags": "worksheet-0", - "slideshow": { - "slide_type": "-" - } - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "{0: {0: [0], 3: [0, 3], 1: [0, 3, 1], 4: [0, 3, 4], 2: [0, 3, 4, 2]}, 1: {1: [1], 3: [1, 3], 0: [1, 3, 0], 4: [1, 3, 4], 2: [1, 3, 4, 2]}, 2: {2: [2], 4: [2, 4], 3: [2, 4, 3], 0: [2, 4, 3, 0], 1: [2, 4, 3, 1]}, 3: {3: [3], 0: [3, 0], 1: [3, 1], 4: [3, 4], 2: [3, 4, 2]}, 4: {4: [4], 2: [4, 2], 3: [4, 3], 0: [4, 3, 0], 1: [4, 3, 1]}}\n", - "[[ 0. 2. 3. 1. 2.]\n", - " [ 2. 0. 3. 1. 2.]\n", - " [ 3. 3. 0. 2. 1.]\n", - " [ 1. 1. 2. 0. 1.]\n", - " [ 2. 2. 1. 1. 0.]]\n" - ] - } - ], - "source": [ - "l = nx.shortest_path(G1)\n", - "print(l)\n", - "\n", - "distances = np.zeros((G1.number_of_nodes(),G1.number_of_nodes()))\n", - "for i in l.keys():\n", - " for j in l[i].keys():\n", - " distances[i,j] = len(l[i][j])-1\n", - "\n", - "print(distances)\n" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.5.2" - }, - "name": "test_lib.ipynb" - }, - "nbformat": 4, - "nbformat_minor": 2 -} From d6abcc24a131964e1c1c3ac8dd2b6358501e78ae Mon Sep 17 00:00:00 2001 From: Benoit GAUZERE Date: Thu, 30 Nov 2017 15:37:51 +0100 Subject: [PATCH 16/16] Minor bug on traversal of shortest path list inutils.py --- pygraph/utils/utils.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pygraph/utils/utils.py b/pygraph/utils/utils.py index 52a85f1..0c7bf60 100644 --- a/pygraph/utils/utils.py +++ b/pygraph/utils/utils.py @@ -5,8 +5,8 @@ import numpy as np def getSPLengths(G1): sp = nx.shortest_path(G1) distances = np.zeros((G1.number_of_nodes(), G1.number_of_nodes())) - for i in np.keys(): - for j in np[i].keys(): + for i in sp.keys(): + for j in sp[i].keys(): distances[i, j] = len(sp[i][j])-1 return distances