Skip to content

Commit b1ae62a

Browse files
authored
Merge pull request #21 from jajupmochi/v0.2
Add ged module.
2 parents 89ba98b + 5eb69de commit b1ae62a

23 files changed

+1816
-28
lines changed

.coveragerc

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,4 @@
11
[run]
2-
omit = gklearn/tests/*
2+
omit =
3+
gklearn/tests/*
4+
gklearn/examples/*
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
# -*- coding: utf-8 -*-
2+
"""compute_graph_edit_distance.ipynb
3+
4+
Automatically generated by Colaboratory.
5+
6+
Original file is located at
7+
https://colab.research.google.com/drive/1Wfgn7WVuyOQQgwOvdUQBz0BzEVdp0YM3
8+
9+
**This script demonstrates how to compute a graph edit distance.**
10+
---
11+
12+
**0. Install `graphkit-learn`.**
13+
"""
14+
15+
"""**1. Get dataset.**"""
16+
17+
from gklearn.utils import Dataset
18+
19+
# Predefined dataset name, use dataset "MUTAG".
20+
ds_name = 'MUTAG'
21+
22+
# Initialize a Dataset.
23+
dataset = Dataset()
24+
# Load predefined dataset "MUTAG".
25+
dataset.load_predefined_dataset(ds_name)
26+
graph1 = dataset.graphs[0]
27+
graph2 = dataset.graphs[1]
28+
print(graph1, graph2)
29+
30+
"""**2. Compute graph edit distance.**"""
31+
32+
from gklearn.ged.env import GEDEnv
33+
34+
35+
ged_env = GEDEnv() # initailize GED environment.
36+
ged_env.set_edit_cost('CONSTANT', # GED cost type.
37+
edit_cost_constants=[3, 3, 1, 3, 3, 1] # edit costs.
38+
)
39+
ged_env.add_nx_graph(graph1, '') # add graph1
40+
ged_env.add_nx_graph(graph2, '') # add graph2
41+
listID = ged_env.get_all_graph_ids() # get list IDs of graphs
42+
ged_env.init(init_type='LAZY_WITHOUT_SHUFFLED_COPIES') # initialize GED environment.
43+
options = {'initialization_method': 'RANDOM', # or 'NODE', etc.
44+
'threads': 1 # parallel threads.
45+
}
46+
ged_env.set_method('BIPARTITE', # GED method.
47+
options # options for GED method.
48+
)
49+
ged_env.init_method() # initialize GED method.
50+
51+
ged_env.run_method(listID[0], listID[1]) # run.
52+
53+
pi_forward = ged_env.get_forward_map(listID[0], listID[1]) # forward map.
54+
pi_backward = ged_env.get_backward_map(listID[0], listID[1]) # backward map.
55+
dis = ged_env.get_upper_bound(listID[0], listID[1]) # GED bewteen two graphs.
56+
print(pi_forward)
57+
print(pi_backward)
58+
print(dis)

gklearn/ged/edit_costs/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
from gklearn.ged.edit_costs.edit_cost import EditCost
2+
from gklearn.ged.edit_costs.constant import Constant

gklearn/ged/edit_costs/constant.py

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
#!/usr/bin/env python3
2+
# -*- coding: utf-8 -*-
3+
"""
4+
Created on Wed Jun 17 17:52:23 2020
5+
6+
@author: ljia
7+
"""
8+
from gklearn.ged.edit_costs import EditCost
9+
10+
11+
class Constant(EditCost):
12+
"""Implements constant edit cost functions.
13+
"""
14+
15+
16+
def __init__(self, node_ins_cost=1, node_del_cost=1, node_rel_cost=1, edge_ins_cost=1, edge_del_cost=1, edge_rel_cost=1):
17+
self.__node_ins_cost = node_ins_cost
18+
self.__node_del_cost = node_del_cost
19+
self.__node_rel_cost = node_rel_cost
20+
self.__edge_ins_cost = edge_ins_cost
21+
self.__edge_del_cost = edge_del_cost
22+
self.__edge_rel_cost = edge_rel_cost
23+
24+
25+
def node_ins_cost_fun(self, node_label):
26+
return self.__node_ins_cost
27+
28+
29+
def node_del_cost_fun(self, node_label):
30+
return self.__node_del_cost
31+
32+
33+
def node_rel_cost_fun(self, node_label_1, node_label_2):
34+
if node_label_1 != node_label_2:
35+
return self.__node_rel_cost
36+
return 0
37+
38+
39+
def edge_ins_cost_fun(self, edge_label):
40+
return self.__edge_ins_cost
41+
42+
43+
def edge_del_cost_fun(self, edge_label):
44+
return self.__edge_del_cost
45+
46+
47+
def edge_rel_cost_fun(self, edge_label_1, edge_label_2):
48+
if edge_label_1 != edge_label_2:
49+
return self.__edge_rel_cost
50+
return 0

gklearn/ged/edit_costs/edit_cost.py

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
#!/usr/bin/env python3
2+
# -*- coding: utf-8 -*-
3+
"""
4+
Created on Wed Jun 17 17:49:24 2020
5+
6+
@author: ljia
7+
"""
8+
9+
10+
class EditCost(object):
11+
12+
13+
def __init__(self):
14+
pass
15+
16+
17+
def node_ins_cost_fun(self, node_label):
18+
"""
19+
/*!
20+
* @brief Node insertions cost function.
21+
* @param[in] node_label A node label.
22+
* @return The cost of inserting a node with label @p node_label.
23+
* @note Must be implemented by derived classes of ged::EditCosts.
24+
*/
25+
"""
26+
return 0
27+
28+
29+
def node_del_cost_fun(self, node_label):
30+
"""
31+
/*!
32+
* @brief Node deletion cost function.
33+
* @param[in] node_label A node label.
34+
* @return The cost of deleting a node with label @p node_label.
35+
* @note Must be implemented by derived classes of ged::EditCosts.
36+
*/
37+
"""
38+
return 0
39+
40+
41+
def node_rel_cost_fun(self, node_label_1, node_label_2):
42+
"""
43+
/*!
44+
* @brief Node relabeling cost function.
45+
* @param[in] node_label_1 A node label.
46+
* @param[in] node_label_2 A node label.
47+
* @return The cost of changing a node's label from @p node_label_1 to @p node_label_2.
48+
* @note Must be implemented by derived classes of ged::EditCosts.
49+
*/
50+
"""
51+
return 0
52+
53+
54+
def edge_ins_cost_fun(self, edge_label):
55+
"""
56+
/*!
57+
* @brief Edge insertion cost function.
58+
* @param[in] edge_label An edge label.
59+
* @return The cost of inserting an edge with label @p edge_label.
60+
* @note Must be implemented by derived classes of ged::EditCosts.
61+
*/
62+
"""
63+
return 0
64+
65+
66+
def edge_del_cost_fun(self, edge_label):
67+
"""
68+
/*!
69+
* @brief Edge deletion cost function.
70+
* @param[in] edge_label An edge label.
71+
* @return The cost of deleting an edge with label @p edge_label.
72+
* @note Must be implemented by derived classes of ged::EditCosts.
73+
*/
74+
"""
75+
return 0
76+
77+
78+
def edge_rel_cost_fun(self, edge_label_1, edge_label_2):
79+
"""
80+
/*!
81+
* @brief Edge relabeling cost function.
82+
* @param[in] edge_label_1 An edge label.
83+
* @param[in] edge_label_2 An edge label.
84+
* @return The cost of changing an edge's label from @p edge_label_1 to @p edge_label_2.
85+
* @note Must be implemented by derived classes of ged::EditCosts.
86+
*/
87+
"""
88+
return 0

gklearn/ged/env/__init__.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,4 @@
1-
from gklearn.ged.env.common_types import AlgorithmState
1+
from gklearn.ged.env.common_types import Options, OptionsStringMap, AlgorithmState
2+
from gklearn.ged.env.ged_data import GEDData
3+
from gklearn.ged.env.ged_env import GEDEnv
24
from gklearn.ged.env.node_map import NodeMap

gklearn/ged/env/common_types.py

Lines changed: 147 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,152 @@
88

99
from enum import Enum, unique
1010

11+
12+
class Options(object):
13+
"""Contains enums for options employed by ged::GEDEnv.
14+
"""
15+
16+
17+
@unique
18+
class GEDMethod(Enum):
19+
"""Selects the method.
20+
"""
21+
# @todo: what is this? #ifdef GUROBI
22+
F1 = 1 # Selects ged::F1.
23+
F2 = 2 # Selects ged::F2.
24+
COMPACT_MIP = 3 # Selects ged::CompactMIP.
25+
BLP_NO_EDGE_LABELS = 4 # Selects ged::BLPNoEdgeLabels.
26+
#endif /* GUROBI */
27+
BRANCH = 5 # Selects ged::Branch.
28+
BRANCH_FAST = 6 # Selects ged::BranchFast.
29+
BRANCH_TIGHT = 7 # Selects ged::BranchTight.
30+
BRANCH_UNIFORM = 8 # Selects ged::BranchUniform.
31+
BRANCH_COMPACT = 9 # Selects ged::BranchCompact.
32+
PARTITION = 10 # Selects ged::Partition.
33+
HYBRID = 11 # Selects ged::Hybrid.
34+
RING = 12 # Selects ged::Ring.
35+
ANCHOR_AWARE_GED = 13 # Selects ged::AnchorAwareGED.
36+
WALKS = 14 # Selects ged::Walks.
37+
IPFP = 15 # Selects ged::IPFP
38+
BIPARTITE = 16 # Selects ged::Bipartite.
39+
SUBGRAPH = 17 # Selects ged::Subgraph.
40+
NODE = 18 # Selects ged::Node.
41+
RING_ML = 19 # Selects ged::RingML.
42+
BIPARTITE_ML = 20 # Selects ged::BipartiteML.
43+
REFINE = 21 # Selects ged::Refine.
44+
BP_BEAM = 22 # Selects ged::BPBeam.
45+
SIMULATED_ANNEALING = 23 # Selects ged::SimulatedAnnealing.
46+
HED = 24 # Selects ged::HED.
47+
STAR = 25 # Selects ged::Star.
48+
49+
50+
@unique
51+
class EditCosts(Enum):
52+
"""Selects the edit costs.
53+
"""
54+
CHEM_1 = 1 # Selects ged::CHEM1.
55+
CHEM_2 = 2 # Selects ged::CHEM2.
56+
CMU = 3 # Selects ged::CMU.
57+
GREC_1 = 4 # Selects ged::GREC1.
58+
GREC_2 = 5 # Selects ged::GREC2.
59+
PROTEIN = 6 # Selects ged::Protein.
60+
FINGERPRINT = 7 # Selects ged::Fingerprint.
61+
LETTER = 8 # Selects ged::Letter.
62+
LETTER2 = 9 # Selects ged:Letter2.
63+
NON_SYMBOLIC = 10 # Selects ged:NonSymbolic.
64+
CONSTANT = 11 # Selects ged::Constant.
65+
66+
67+
@unique
68+
class InitType(Enum):
69+
"""@brief Selects the initialization type of the environment.
70+
* @details If eager initialization is selected, all edit costs are pre-computed when initializing the environment.
71+
* Otherwise, they are computed at runtime. If initialization with shuffled copies is selected, shuffled copies of
72+
* all graphs are created. These copies are used when calling ged::GEDEnv::run_method() with two identical graph IDs.
73+
* In this case, one of the IDs is internally replaced by the ID of the shuffled copy and the graph is hence
74+
* compared to an isomorphic but non-identical graph. If initialization without shuffled copies is selected, no shuffled copies
75+
* are created and calling ged::GEDEnv::run_method() with two identical graph IDs amounts to comparing a graph to itself.
76+
"""
77+
LAZY_WITHOUT_SHUFFLED_COPIES = 1 # Lazy initialization, no shuffled graph copies are constructed.
78+
EAGER_WITHOUT_SHUFFLED_COPIES = 2 # Eager initialization, no shuffled graph copies are constructed.
79+
LAZY_WITH_SHUFFLED_COPIES = 3 # Lazy initialization, shuffled graph copies are constructed.
80+
EAGER_WITH_SHUFFLED_COPIES = 4 # Eager initialization, shuffled graph copies are constructed.
81+
82+
83+
@unique
84+
class AlgorithmState(Enum):
85+
"""can be used to specify the state of an algorithm.
86+
"""
87+
CALLED = 1 # The algorithm has been called.
88+
INITIALIZED = 2 # The algorithm has been initialized.
89+
CONVERGED = 3 # The algorithm has converged.
90+
TERMINATED = 4 # The algorithm has terminated.
91+
92+
93+
class OptionsStringMap(object):
94+
95+
96+
# Map of available computation methods between enum type and string.
97+
GEDMethod = {
98+
"BRANCH": Options.GEDMethod.BRANCH,
99+
"BRANCH_FAST": Options.GEDMethod.BRANCH_FAST,
100+
"BRANCH_TIGHT": Options.GEDMethod.BRANCH_TIGHT,
101+
"BRANCH_UNIFORM": Options.GEDMethod.BRANCH_UNIFORM,
102+
"BRANCH_COMPACT": Options.GEDMethod.BRANCH_COMPACT,
103+
"PARTITION": Options.GEDMethod.PARTITION,
104+
"HYBRID": Options.GEDMethod.HYBRID,
105+
"RING": Options.GEDMethod.RING,
106+
"ANCHOR_AWARE_GED": Options.GEDMethod.ANCHOR_AWARE_GED,
107+
"WALKS": Options.GEDMethod.WALKS,
108+
"IPFP": Options.GEDMethod.IPFP,
109+
"BIPARTITE": Options.GEDMethod.BIPARTITE,
110+
"SUBGRAPH": Options.GEDMethod.SUBGRAPH,
111+
"NODE": Options.GEDMethod.NODE,
112+
"RING_ML": Options.GEDMethod.RING_ML,
113+
"BIPARTITE_ML": Options.GEDMethod.BIPARTITE_ML,
114+
"REFINE": Options.GEDMethod.REFINE,
115+
"BP_BEAM": Options.GEDMethod.BP_BEAM,
116+
"SIMULATED_ANNEALING": Options.GEDMethod.SIMULATED_ANNEALING,
117+
"HED": Options.GEDMethod.HED,
118+
"STAR": Options.GEDMethod.STAR,
119+
# ifdef GUROBI
120+
"F1": Options.GEDMethod.F1,
121+
"F2": Options.GEDMethod.F2,
122+
"COMPACT_MIP": Options.GEDMethod.COMPACT_MIP,
123+
"BLP_NO_EDGE_LABELS": Options.GEDMethod.BLP_NO_EDGE_LABELS
124+
}
125+
126+
127+
# Map of available edit cost functions between enum type and string.
128+
EditCosts = {
129+
"CHEM_1": Options.EditCosts.CHEM_1,
130+
"CHEM_2": Options.EditCosts.CHEM_2,
131+
"CMU": Options.EditCosts.CMU,
132+
"GREC_1": Options.EditCosts.GREC_1,
133+
"GREC_2": Options.EditCosts.GREC_2,
134+
"LETTER": Options.EditCosts.LETTER,
135+
"LETTER2": Options.EditCosts.LETTER2,
136+
"NON_SYMBOLIC": Options.EditCosts.NON_SYMBOLIC,
137+
"FINGERPRINT": Options.EditCosts.FINGERPRINT,
138+
"PROTEIN": Options.EditCosts.PROTEIN,
139+
"CONSTANT": Options.EditCosts.CONSTANT
140+
}
141+
142+
# Map of available initialization types of the environment between enum type and string.
143+
InitType = {
144+
"LAZY_WITHOUT_SHUFFLED_COPIES": Options.InitType.LAZY_WITHOUT_SHUFFLED_COPIES,
145+
"EAGER_WITHOUT_SHUFFLED_COPIES": Options.InitType.EAGER_WITHOUT_SHUFFLED_COPIES,
146+
"LAZY_WITH_SHUFFLED_COPIES": Options.InitType.LAZY_WITH_SHUFFLED_COPIES,
147+
"LAZY_WITH_SHUFFLED_COPIES": Options.InitType.LAZY_WITH_SHUFFLED_COPIES
148+
}
149+
150+
11151
@unique
12152
class AlgorithmState(Enum):
13-
"""can be used to specify the state of an algorithm.
14-
"""
15-
CALLED = 1 # The algorithm has been called.
16-
INITIALIZED = 2 # The algorithm has been initialized.
17-
CONVERGED = 3 # The algorithm has converged.
18-
TERMINATED = 4 # The algorithm has terminated.
153+
"""can be used to specify the state of an algorithm.
154+
"""
155+
CALLED = 1 # The algorithm has been called.
156+
INITIALIZED = 2 # The algorithm has been initialized.
157+
CONVERGED = 3 # The algorithm has converged.
158+
TERMINATED = 4 # The algorithm has terminated.
159+

0 commit comments

Comments
 (0)