|
|
@@ -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 |