diff --git a/lang/fr/gklearn/tests/ged/test_get_nb_edit_operations_symbolic_cml.py b/lang/fr/gklearn/tests/ged/test_get_nb_edit_operations_symbolic_cml.py new file mode 100644 index 0000000..aa40cca --- /dev/null +++ b/lang/fr/gklearn/tests/ged/test_get_nb_edit_operations_symbolic_cml.py @@ -0,0 +1,122 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +Created on Mon Jul 6 12:08:24 2020 + +@author: ljia +""" +import random +import numpy as np + +def test_get_nb_edit_operations_symbolic_cml(): + """Test get_nb_edit_operations_symbolic_cml(). + """ + """**1. Get dataset.**""" + + from gklearn.utils import Dataset + + # Predefined dataset name, use dataset "MUTAG". + ds_name = 'MUTAG' + + # Initialize a Dataset. + dataset = Dataset() + # Load predefined dataset "MUTAG". + dataset.load_predefined_dataset(ds_name) + graph1 = dataset.graphs[0] + graph2 = dataset.graphs[1] + + """**2. Compute graph edit distance.**""" + +# try: + # Initialize label costs randomly. + node_label_costs, edge_label_costs = _initialize_label_costs(dataset) + + # Compute GEDs. + pi_forward, pi_backward, dis, node_labels, edge_labels = _compute_ged(dataset, node_label_costs, edge_label_costs) + + + # Compute numbers of edit operations. + + from gklearn.ged.util.util import get_nb_edit_operations_symbolic_cml + + n_edit_operations = get_nb_edit_operations_symbolic_cml(graph1, graph2, pi_forward, pi_backward, node_labels, edge_labels) + + assert np.abs((np.dot(np.concatenate((node_label_costs, edge_label_costs)), n_edit_operations) - dis) / dis) < 10e-6 + +# except Exception as exception: +# assert False, exception + + +def _initialize_label_costs(dataset): + node_label_costs = _initialize_node_label_costs(dataset) + edge_label_costs = _initialize_edge_label_costs(dataset) + return node_label_costs, edge_label_costs + + +def _initialize_node_label_costs(dataset): + # Get list of node labels. + nls = dataset.get_all_node_labels() + # Generate random costs. + nb_nl = int((len(nls) * (len(nls) - 1)) / 2 + 2 * len(nls)) + rand_costs = random.sample(range(1, 10 * nb_nl + 1), nb_nl) + rand_costs /= np.max(rand_costs) + + return rand_costs + + +def _initialize_edge_label_costs(dataset): + # Get list of edge labels. + els = dataset.get_all_edge_labels() + # Generate random costs. + nb_el = int((len(els) * (len(els) - 1)) / 2 + 2 * len(els)) + rand_costs = random.sample(range(1, 10 * nb_el + 1), nb_el) + rand_costs /= np.max(rand_costs) + + return rand_costs + + +def _compute_ged(dataset, node_label_costs, edge_label_costs): + from gklearn.ged.env import GEDEnv + from gklearn.ged.util.util import label_costs_to_matrix + import networkx as nx + + ged_env = GEDEnv() # initailize GED environment. + ged_env.set_edit_cost('CONSTANT', # GED cost type. + edit_cost_constants=[3, 3, 1, 3, 3, 1] # edit costs. + ) + for g in dataset.graphs: + ged_env.add_nx_graph(g, '') # add graphs + + node_labels = ged_env.get_all_node_labels() + edge_labels = ged_env.get_all_edge_labels() + listID = ged_env.get_all_graph_ids() # get list IDs of graphs + ged_env.set_label_costs(label_costs_to_matrix(node_label_costs, len(node_labels)), + label_costs_to_matrix(edge_label_costs, len(edge_labels))) + ged_env.init(init_type='LAZY_WITHOUT_SHUFFLED_COPIES') # initialize GED environment. + options = {'initialization_method': 'RANDOM', # or 'NODE', etc. + 'threads': 1 # parallel threads. + } + ged_env.set_method('BIPARTITE', # GED method. + options # options for GED method. + ) + ged_env.init_method() # initialize GED method. + + ged_env.run_method(listID[0], listID[1]) # run. + + pi_forward = ged_env.get_forward_map(listID[0], listID[1]) # forward map. + pi_backward = ged_env.get_backward_map(listID[0], listID[1]) # backward map. + dis = ged_env.get_upper_bound(listID[0], listID[1]) # GED bewteen two graphs. + + # make the map label correct (label remove map as np.inf) + nodes1 = [n for n in dataset.graphs[0].nodes()] + nodes2 = [n for n in dataset.graphs[1].nodes()] + nb1 = nx.number_of_nodes(dataset.graphs[0]) + nb2 = nx.number_of_nodes(dataset.graphs[1]) + pi_forward = [nodes2[pi] if pi < nb2 else np.inf for pi in pi_forward] + pi_backward = [nodes1[pi] if pi < nb1 else np.inf for pi in pi_backward] + + return pi_forward, pi_backward, dis, node_labels, edge_labels + + +if __name__ == "__main__": + test_get_nb_edit_operations_symbolic_cml() \ No newline at end of file