@@ -23,6 +23,8 @@ def __init__(self):
23
23
self ._edit_cost = None
24
24
self ._node_costs = None
25
25
self ._edge_costs = None
26
+ self ._node_label_costs = None
27
+ self ._edge_label_costs = None
26
28
self ._node_labels = []
27
29
self ._edge_labels = []
28
30
self ._init_type = Options .InitType .EAGER_WITHOUT_SHUFFLED_COPIES
@@ -41,6 +43,17 @@ def num_graphs(self):
41
43
return len (self ._graphs )
42
44
43
45
46
+ def graph (self , graph_id ):
47
+ """
48
+ /*!
49
+ * @brief Provides access to a graph.
50
+ * @param[in] graph_id The ID of the graph.
51
+ * @return Constant reference to the graph with ID @p graph_id.
52
+ */
53
+ """
54
+ return self ._graphs [graph_id ]
55
+
56
+
44
57
def shuffled_graph_copies_available (self ):
45
58
"""
46
59
/*!
@@ -51,6 +64,16 @@ def shuffled_graph_copies_available(self):
51
64
return (self ._init_type == Options .InitType .EAGER_WITH_SHUFFLED_COPIES or self ._init_type == Options .InitType .LAZY_WITH_SHUFFLED_COPIES )
52
65
53
66
67
+ def num_graphs_without_shuffled_copies (self ):
68
+ """
69
+ /*!
70
+ * @brief Returns the number of graphs in the instance without the shuffled copies.
71
+ * @return Number of graphs without shuffled copies contained in the instance.
72
+ */
73
+ """
74
+ return self ._num_graphs_without_shuffled_copies
75
+
76
+
54
77
def node_cost (self , label1 , label2 ):
55
78
"""
56
79
/*!
@@ -63,15 +86,21 @@ def node_cost(self, label1, label2):
63
86
* and 0 otherwise.
64
87
*/
65
88
"""
66
- if self ._eager_init (): # @todo: check if correct
67
- return self ._node_costs [label1 , label2 ]
68
- if label1 == label2 :
69
- return 0
70
- if label1 == SpecialLabel .DUMMY : # @todo: check dummy
71
- return self ._edit_cost .node_ins_cost_fun (label2 ) # self._node_labels[label2 - 1]) # @todo: check
72
- if label2 == SpecialLabel .DUMMY : # @todo: check dummy
73
- return self ._edit_cost .node_del_cost_fun (label1 ) # self._node_labels[label1 - 1])
74
- return self ._edit_cost .node_rel_cost_fun (label1 , label2 ) # self._node_labels[label1 - 1], self._node_labels[label2 - 1])
89
+ if self ._node_label_costs is None :
90
+ if self ._eager_init (): # @todo: check if correct
91
+ return self ._node_costs [label1 , label2 ]
92
+ if label1 == label2 :
93
+ return 0
94
+ if label1 == SpecialLabel .DUMMY : # @todo: check dummy
95
+ return self ._edit_cost .node_ins_cost_fun (label2 ) # self._node_labels[label2 - 1]) # @todo: check
96
+ if label2 == SpecialLabel .DUMMY : # @todo: check dummy
97
+ return self ._edit_cost .node_del_cost_fun (label1 ) # self._node_labels[label1 - 1])
98
+ return self ._edit_cost .node_rel_cost_fun (label1 , label2 ) # self._node_labels[label1 - 1], self._node_labels[label2 - 1])
99
+ # use pre-computed node label costs.
100
+ else :
101
+ id1 = 0 if label1 == SpecialLabel .DUMMY else self ._node_label_to_id (label1 ) # @todo: this is slow.
102
+ id2 = 0 if label2 == SpecialLabel .DUMMY else self ._node_label_to_id (label2 )
103
+ return self ._node_label_costs [id1 , id2 ]
75
104
76
105
77
106
def edge_cost (self , label1 , label2 ):
@@ -86,15 +115,22 @@ def edge_cost(self, label1, label2):
86
115
* and 0 otherwise.
87
116
*/
88
117
"""
89
- if self ._eager_init (): # @todo: check if correct
90
- return self ._node_costs [label1 , label2 ]
91
- if label1 == label2 :
92
- return 0
93
- if label1 == SpecialLabel .DUMMY :
94
- return self ._edit_cost .edge_ins_cost_fun (label2 ) # self._edge_labels[label2 - 1])
95
- if label2 == SpecialLabel .DUMMY :
96
- return self ._edit_cost .edge_del_cost_fun (label1 ) # self._edge_labels[label1 - 1])
97
- return self ._edit_cost .edge_rel_cost_fun (label1 , label2 ) # self._edge_labels[label1 - 1], self._edge_labels[label2 - 1])
118
+ if self ._edge_label_costs is None :
119
+ if self ._eager_init (): # @todo: check if correct
120
+ return self ._node_costs [label1 , label2 ]
121
+ if label1 == label2 :
122
+ return 0
123
+ if label1 == SpecialLabel .DUMMY :
124
+ return self ._edit_cost .edge_ins_cost_fun (label2 ) # self._edge_labels[label2 - 1])
125
+ if label2 == SpecialLabel .DUMMY :
126
+ return self ._edit_cost .edge_del_cost_fun (label1 ) # self._edge_labels[label1 - 1])
127
+ return self ._edit_cost .edge_rel_cost_fun (label1 , label2 ) # self._edge_labels[label1 - 1], self._edge_labels[label2 - 1])
128
+
129
+ # use pre-computed edge label costs.
130
+ else :
131
+ id1 = 0 if label1 == SpecialLabel .DUMMY else self ._edge_label_to_id (label1 ) # @todo: this is slow.
132
+ id2 = 0 if label2 == SpecialLabel .DUMMY else self ._edge_label_to_id (label2 )
133
+ return self ._edge_label_costs [id1 , id2 ]
98
134
99
135
100
136
def compute_induced_cost (self , g , h , node_map ):
@@ -177,5 +213,37 @@ def _set_edit_cost(self, edit_cost, edit_cost_constants):
177
213
self ._delete_edit_cost = True
178
214
179
215
216
+ def id_to_node_label (self , label_id ):
217
+ if label_id > len (self ._node_labels ) or label_id == 0 :
218
+ raise Exception ('Invalid node label ID' , str (label_id ), '.' )
219
+ return self ._node_labels [label_id - 1 ]
220
+
221
+
222
+ def _node_label_to_id (self , node_label ):
223
+ n_id = 0
224
+ for n_l in self ._node_labels :
225
+ if n_l == node_label :
226
+ return n_id + 1
227
+ n_id += 1
228
+ self ._node_labels .append (node_label )
229
+ return n_id + 1
230
+
231
+
232
+ def id_to_edge_label (self , label_id ):
233
+ if label_id > len (self ._edge_labels ) or label_id == 0 :
234
+ raise Exception ('Invalid edge label ID' , str (label_id ), '.' )
235
+ return self ._edge_labels [label_id - 1 ]
236
+
237
+
238
+ def _edge_label_to_id (self , edge_label ):
239
+ e_id = 0
240
+ for e_l in self ._edge_labels :
241
+ if e_l == edge_label :
242
+ return e_id + 1
243
+ e_id += 1
244
+ self ._edge_labels .append (edge_label )
245
+ return e_id + 1
246
+
247
+
180
248
def _eager_init (self ):
181
249
return (self ._init_type == Options .InitType .EAGER_WITHOUT_SHUFFLED_COPIES or self ._init_type == Options .InitType .EAGER_WITH_SHUFFLED_COPIES )
0 commit comments