import numpy as np from scipy.optimize import linear_sum_assignment 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, 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_ 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(): """ 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 """ 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.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.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.cf_.cei([v, nbr_v, G2[v][nbr_v]], G2) j += 1 row_ind, col_ind = self.lsap_solver_(sub_C) cost = np.sum(sub_C[row_ind, col_ind]) return self.cf_.cns(u, v, G1, G2) + cost def cnd(self, u, G1): cost = 0 for nbr in G1[u]: 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 += self.cf_.cei([v,nbr,G2[v][nbr]], G2) return self.cf_.cni(v, G2) + cost 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 """ 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.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.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.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 = self.lsap_solver_(sub_C) cost = np.sum(sub_C[row_ind, col_ind]) return self.cf_.cns(u, v, G1, G2) + cost def cnd(self, u, G1): cost = 0 for nbr in G1[u]: 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 += self.cf_.cei([v, nbr, G2[v][nbr]], G2) return self.cf_.cni(v, G2) + cost