From 02f195ba7680985fd5636f5c97ff7a7744765cb4 Mon Sep 17 00:00:00 2001 From: linlin Date: Mon, 5 Oct 2020 16:38:54 +0200 Subject: [PATCH] New translations ged_data.py (French) --- lang/fr/gklearn/ged/env/ged_data.py | 249 ++++++++++++++++++++++++++++++++++++ 1 file changed, 249 insertions(+) create mode 100644 lang/fr/gklearn/ged/env/ged_data.py diff --git a/lang/fr/gklearn/ged/env/ged_data.py b/lang/fr/gklearn/ged/env/ged_data.py new file mode 100644 index 0000000..0e6881f --- /dev/null +++ b/lang/fr/gklearn/ged/env/ged_data.py @@ -0,0 +1,249 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +Created on Wed Jun 17 15:05:01 2020 + +@author: ljia +""" +from gklearn.ged.env import Options, OptionsStringMap +from gklearn.ged.edit_costs import Constant +from gklearn.utils import SpecialLabel, dummy_node + + +class GEDData(object): + + + def __init__(self): + self._graphs = [] + self._graph_names = [] + self._graph_classes = [] + self._num_graphs_without_shuffled_copies = 0 + self._strings_to_internal_node_ids = [] + self._internal_node_ids_to_strings = [] + self._edit_cost = None + self._node_costs = None + self._edge_costs = None + self._node_label_costs = None + self._edge_label_costs = None + self._node_labels = [] + self._edge_labels = [] + self._init_type = Options.InitType.EAGER_WITHOUT_SHUFFLED_COPIES + self._delete_edit_cost = True + self._max_num_nodes = 0 + self._max_num_edges = 0 + + + def num_graphs(self): + """ + /*! + * @brief Returns the number of graphs. + * @return Number of graphs in the instance. + */ + """ + return len(self._graphs) + + + def graph(self, graph_id): + """ + /*! + * @brief Provides access to a graph. + * @param[in] graph_id The ID of the graph. + * @return Constant reference to the graph with ID @p graph_id. + */ + """ + return self._graphs[graph_id] + + + def shuffled_graph_copies_available(self): + """ + /*! + * @brief Checks if shuffled graph copies are available. + * @return Boolean @p true if shuffled graph copies are available. + */ + """ + return (self._init_type == Options.InitType.EAGER_WITH_SHUFFLED_COPIES or self._init_type == Options.InitType.LAZY_WITH_SHUFFLED_COPIES) + + + def num_graphs_without_shuffled_copies(self): + """ + /*! + * @brief Returns the number of graphs in the instance without the shuffled copies. + * @return Number of graphs without shuffled copies contained in the instance. + */ + """ + return self._num_graphs_without_shuffled_copies + + + def node_cost(self, label1, label2): + """ + /*! + * @brief Returns node relabeling, insertion, or deletion cost. + * @param[in] label1 First node label. + * @param[in] label2 Second node label. + * @return Node relabeling cost if @p label1 and @p label2 are both different from ged::dummy_label(), + * node insertion cost if @p label1 equals ged::dummy_label and @p label2 does not, + * node deletion cost if @p label1 does not equal ged::dummy_label and @p label2 does, + * and 0 otherwise. + */ + """ + if self._node_label_costs is None: + if self._eager_init(): # @todo: check if correct + return self._node_costs[label1, label2] + if label1 == label2: + return 0 + if label1 == SpecialLabel.DUMMY: # @todo: check dummy + return self._edit_cost.node_ins_cost_fun(label2) # self._node_labels[label2 - 1]) # @todo: check + if label2 == SpecialLabel.DUMMY: # @todo: check dummy + return self._edit_cost.node_del_cost_fun(label1) # self._node_labels[label1 - 1]) + return self._edit_cost.node_rel_cost_fun(label1, label2) # self._node_labels[label1 - 1], self._node_labels[label2 - 1]) + # use pre-computed node label costs. + else: + id1 = 0 if label1 == SpecialLabel.DUMMY else self._node_label_to_id(label1) # @todo: this is slow. + id2 = 0 if label2 == SpecialLabel.DUMMY else self._node_label_to_id(label2) + return self._node_label_costs[id1, id2] + + + def edge_cost(self, label1, label2): + """ + /*! + * @brief Returns edge relabeling, insertion, or deletion cost. + * @param[in] label1 First edge label. + * @param[in] label2 Second edge label. + * @return Edge relabeling cost if @p label1 and @p label2 are both different from ged::dummy_label(), + * edge insertion cost if @p label1 equals ged::dummy_label and @p label2 does not, + * edge deletion cost if @p label1 does not equal ged::dummy_label and @p label2 does, + * and 0 otherwise. + */ + """ + if self._edge_label_costs is None: + if self._eager_init(): # @todo: check if correct + return self._node_costs[label1, label2] + if label1 == label2: + return 0 + if label1 == SpecialLabel.DUMMY: + return self._edit_cost.edge_ins_cost_fun(label2) # self._edge_labels[label2 - 1]) + if label2 == SpecialLabel.DUMMY: + return self._edit_cost.edge_del_cost_fun(label1) # self._edge_labels[label1 - 1]) + return self._edit_cost.edge_rel_cost_fun(label1, label2) # self._edge_labels[label1 - 1], self._edge_labels[label2 - 1]) + + # use pre-computed edge label costs. + else: + id1 = 0 if label1 == SpecialLabel.DUMMY else self._edge_label_to_id(label1) # @todo: this is slow. + id2 = 0 if label2 == SpecialLabel.DUMMY else self._edge_label_to_id(label2) + return self._edge_label_costs[id1, id2] + + + def compute_induced_cost(self, g, h, node_map): + """ + /*! + * @brief Computes the edit cost between two graphs induced by a node map. + * @param[in] g Input graph. + * @param[in] h Input graph. + * @param[in,out] node_map Node map whose induced edit cost is to be computed. + */ + """ + cost = 0 + + # collect node costs + for node in g.nodes(): + image = node_map.image(node) + label2 = (SpecialLabel.DUMMY if image == dummy_node() else h.nodes[image]['label']) + cost += self.node_cost(g.nodes[node]['label'], label2) + for node in h.nodes(): + pre_image = node_map.pre_image(node) + if pre_image == dummy_node(): + cost += self.node_cost(SpecialLabel.DUMMY, h.nodes[node]['label']) + + # collect edge costs + for (n1, n2) in g.edges(): + image1 = node_map.image(n1) + image2 = node_map.image(n2) + label2 = (h.edges[(image2, image1)]['label'] if h.has_edge(image2, image1) else SpecialLabel.DUMMY) + cost += self.edge_cost(g.edges[(n1, n2)]['label'], label2) + for (n1, n2) in h.edges(): + if not g.has_edge(node_map.pre_image(n2), node_map.pre_image(n1)): + cost += self.edge_cost(SpecialLabel.DUMMY, h.edges[(n1, n2)]['label']) + + node_map.set_induced_cost(cost) + + + def _set_edit_cost(self, edit_cost, edit_cost_constants): + if self._delete_edit_cost: + self._edit_cost = None + + if isinstance(edit_cost, str): + edit_cost = OptionsStringMap.EditCosts[edit_cost] + + if edit_cost == Options.EditCosts.CHEM_1: + if len(edit_cost_constants) == 4: + self._edit_cost = CHEM1(edit_cost_constants[0], edit_cost_constants[1], edit_cost_constants[2], edit_cost_constants[3]) + elif len(edit_cost_constants) == 0: + self._edit_cost = CHEM1() + else: + raise Exception('Wrong number of constants for selected edit costs Options::EditCosts::CHEM_1. Expected: 4 or 0; actual:', len(edit_cost_constants), '.') + elif edit_cost == Options.EditCosts.LETTER: + if len(edit_cost_constants) == 3: + self._edit_cost = Letter(edit_cost_constants[0], edit_cost_constants[1], edit_cost_constants[2]) + elif len(edit_cost_constants) == 0: + self._edit_cost = Letter() + else: + raise Exception('Wrong number of constants for selected edit costs Options::EditCosts::LETTER. Expected: 3 or 0; actual:', len(edit_cost_constants), '.') + elif edit_cost == Options.EditCosts.LETTER2: + if len(edit_cost_constants) == 5: + self._edit_cost = Letter2(edit_cost_constants[0], edit_cost_constants[1], edit_cost_constants[2], edit_cost_constants[3], edit_cost_constants[4]) + elif len(edit_cost_constants) == 0: + self._edit_cost = Letter2() + else: + raise Exception('Wrong number of constants for selected edit costs Options::EditCosts::LETTER2. Expected: 5 or 0; actual:', len(edit_cost_constants), '.') + elif edit_cost == Options.EditCosts.NON_SYMBOLIC: + if len(edit_cost_constants) == 6: + self._edit_cost = NonSymbolic(edit_cost_constants[0], edit_cost_constants[1], edit_cost_constants[2], edit_cost_constants[3], edit_cost_constants[4], edit_cost_constants[5]) + elif len(edit_cost_constants) == 0: + self._edit_cost = NonSymbolic() + else: + raise Exception('Wrong number of constants for selected edit costs Options::EditCosts::NON_SYMBOLIC. Expected: 6 or 0; actual:', len(edit_cost_constants), '.') + elif edit_cost == Options.EditCosts.CONSTANT: + if len(edit_cost_constants) == 6: + self._edit_cost = Constant(edit_cost_constants[0], edit_cost_constants[1], edit_cost_constants[2], edit_cost_constants[3], edit_cost_constants[4], edit_cost_constants[5]) + elif len(edit_cost_constants) == 0: + self._edit_cost = Constant() + else: + raise Exception('Wrong number of constants for selected edit costs Options::EditCosts::CONSTANT. Expected: 6 or 0; actual:', len(edit_cost_constants), '.') + + self._delete_edit_cost = True + + + def id_to_node_label(self, label_id): + if label_id > len(self._node_labels) or label_id == 0: + raise Exception('Invalid node label ID', str(label_id), '.') + return self._node_labels[label_id - 1] + + + def _node_label_to_id(self, node_label): + n_id = 0 + for n_l in self._node_labels: + if n_l == node_label: + return n_id + 1 + n_id += 1 + self._node_labels.append(node_label) + return n_id + 1 + + + def id_to_edge_label(self, label_id): + if label_id > len(self._edge_labels) or label_id == 0: + raise Exception('Invalid edge label ID', str(label_id), '.') + return self._edge_labels[label_id - 1] + + + def _edge_label_to_id(self, edge_label): + e_id = 0 + for e_l in self._edge_labels: + if e_l == edge_label: + return e_id + 1 + e_id += 1 + self._edge_labels.append(edge_label) + return e_id + 1 + + + def _eager_init(self): + return (self._init_type == Options.InitType.EAGER_WITHOUT_SHUFFLED_COPIES or self._init_type == Options.InitType.EAGER_WITH_SHUFFLED_COPIES) \ No newline at end of file