27 #ifndef SRC_METHODS_REFINE_IPP_ 28 #define SRC_METHODS_REFINE_IPP_ 33 template<
class UserNodeLabel,
class UserEdgeLabel>
34 Refine<UserNodeLabel, UserEdgeLabel>::
37 template<
class UserNodeLabel,
class UserEdgeLabel>
38 Refine<UserNodeLabel, UserEdgeLabel>::
39 Refine(
const GEDData<UserNodeLabel, UserEdgeLabel> & ged_data) :
40 LSBasedMethod<UserNodeLabel, UserEdgeLabel>(ged_data),
43 add_dummy_assignment_{
true} {}
46 template<
class UserNodeLabel,
class UserEdgeLabel>
50 output_node_map = initial_node_map;
51 double best_swap_cost{0.0};
53 std::size_t swap_size{2};
54 while ((output_node_map.
induced_cost() > lower_bound) and ((best_swap_cost < 0) or (swap_size <= max_swap_size_))) {
55 std::vector<NodeMap::Assignment> assignments;
57 if (add_dummy_assignment_) {
61 if (swap_size > assignments.size()) {
65 std::vector<std::size_t> swapped_original_indices;
66 for (std::size_t i=0; i<swap_size; i++) {
67 swapped_original_indices.emplace_back(i);
71 std::vector<NodeMap::Assignment> swapped_original_assignments;
72 for(std::size_t index : swapped_original_indices){
73 swapped_original_assignments.emplace_back(assignments[index]);
76 bool real_node_on_left{
false};
77 bool real_node_on_right{
false};
78 for (
const auto & assignment : swapped_original_assignments) {
81 if (real_node_on_left and real_node_on_right) {
85 if (not (real_node_on_left and real_node_on_right)) {
89 std::vector<std::size_t> cycle(swap_size-1);
90 for (std::size_t i=0; i < swap_size-1;i++) {
95 std::vector<NodeMap::Assignment> swapped_new_assignments;
96 NodeMap::Assignment original_assignment(swapped_original_assignments.at(0));
97 for (std::size_t i=0; i < swap_size - 1; i++) {
98 swapped_new_assignments.emplace_back(swapped_original_assignments.at(cycle.at(i)).first, original_assignment.second);
99 original_assignment = swapped_original_assignments.at(cycle.at(i));
101 swapped_new_assignments.emplace_back(swapped_original_assignments.at(0).first, original_assignment.second);
103 current_swap.original_assignments = swapped_original_assignments;
104 current_swap.new_assignments = swapped_new_assignments;
105 double current_swap_cost = current_swap.cost(g, h, this->
ged_data_, output_node_map, naive_);
106 if (current_swap_cost - best_swap_cost < -0.000000001) {
107 best_swap_cost = current_swap_cost;
108 best_swap = current_swap;
110 }
while (std::next_permutation(cycle.data(), cycle.data() + swap_size-1));
111 }
while (this->next_subset_(assignments.size(), swapped_original_indices));
112 if (best_swap_cost < -0.000000001) {
113 best_swap.do_swap(output_node_map, best_swap_cost);
114 best_swap_cost = 0.0;
118 best_swap_cost = 0.0;
125 template<
class UserNodeLabel,
class UserEdgeLabel>
128 next_subset_(
const std::size_t set_size, std::vector<std::size_t> & subset){
132 std::size_t subset_size = subset.size();
133 std::size_t index_first_changed_element = subset_size - 1;
134 while (subset.at(index_first_changed_element) == set_size-subset_size+index_first_changed_element) {
135 if (index_first_changed_element==0) {
138 index_first_changed_element--;
140 std::size_t index_first_changed_element_in_set = subset[index_first_changed_element];
142 for (std::size_t index_changed_element{index_first_changed_element}; index_changed_element < subset_size; index_changed_element++){
143 subset[index_changed_element] = index_first_changed_element_in_set + index_changed_element - index_first_changed_element+1;
149 template<
class UserNodeLabel,
class UserEdgeLabel>
153 if (option ==
"max-swap-size") {
155 max_swap_size_ = std::stoul(arg);
158 throw Error(std::string(
"Invalid argument \"") + arg +
"\" for option max-swap-size. Usage: options = \"[--max-swap-size <convertible to int greater equal 2>]\"");
160 if (max_swap_size_ < 2) {
161 throw Error(std::string(
"Invalid argument \"") + arg +
"\" for option max-swap-size. Usage: options = \"[--max-swap-size <convertible to int greater equal 2>]\"");
165 else if (option ==
"naive") {
169 else if (arg !=
"FALSE") {
170 throw Error(std::string(
"Invalid argument \"") + arg +
"\" for option naive. Usage: options = \"[--naive <TRUE|FALSE>]\"");
174 else if (option ==
"add-dummy-assignment") {
175 if (arg ==
"FALSE") {
176 add_dummy_assignment_ =
false;
178 else if (arg !=
"TRUE") {
179 throw Error(std::string(
"Invalid argument \"") + arg +
"\" for option add-dummy-assignment. Usage: options = \"[--add-dummy-assignment <TRUE|FALSE>]\"");
186 template<
class UserNodeLabel,
class UserEdgeLabel>
192 add_dummy_assignment_ =
true;
195 template<
class UserNodeLabel,
class UserEdgeLabel>
199 return "[--max-swap-size <arg>] [--naive <arg>] [--add-dummy-assignment <arg>]";
203 template<
class UserNodeLabel,
class UserEdgeLabel>
211 this->do_swap(node_map);
214 this->undo_swap(node_map);
217 else if (this->original_assignments.size() == 2){
218 delta = ged_data.
swap_cost(g, h, original_assignments[0], original_assignments[1], node_map);
223 std::vector<GEDGraph::NodeID> g_swapped_vertices;
224 std::vector<GEDGraph::NodeID> h_swapped_vertices;
226 for(
const auto & assignment : this->original_assignments){
227 g_swapped_vertices.push_back(assignment.first);
228 h_swapped_vertices.push_back(assignment.second);
233 std::vector<GEDGraph::EdgeID> g_incident_edges;
234 std::vector<GEDGraph::EdgeID> h_incident_edges;
236 for(std::size_t g_vertex_index{0}; g_vertex_index< g_swapped_vertices.size();g_vertex_index++){
241 bool added_edge = false ;
242 for(std::size_t i=0; i<g_vertex_index; ++i){
243 if (g.
head(*edge) == g_swapped_vertices[i]) {
249 g_incident_edges.push_back(*edge);
254 for(std::size_t h_vertex_index{0}; h_vertex_index< h_swapped_vertices.size();h_vertex_index++){
259 bool added_edge = false ;
260 for(std::size_t i=0; i<h_vertex_index; ++i){
261 if (h.
head(*edge) == h_swapped_vertices[i]) {
267 h_incident_edges.push_back(*edge);
273 for(
auto&& assignment: this->original_assignments){
276 for(
auto&& assignment: this->new_assignments){
280 for (
const auto & edge : g_incident_edges) {
283 for (
const auto & edge : h_incident_edges) {
289 this->do_swap(node_map);
291 for (
const auto & edge : g_incident_edges) {
294 for (
const auto & edge : h_incident_edges) {
300 this->undo_swap(node_map);
307 template<
class UserNodeLabel,
class UserEdgeLabel>
312 for(
auto new_assignment : this->new_assignments){
313 node_map.
add_assignment(new_assignment.first,new_assignment.second);
318 template<
class UserNodeLabel,
class UserEdgeLabel>
323 for(
auto new_assignment : this->original_assignments)
324 node_map.
add_assignment(new_assignment.first,new_assignment.second);
327 template<
class UserNodeLabel,
class UserEdgeLabel>
332 std::stringstream ss;
333 ss <<
"original assignments: { ";
334 for (
const auto & assignment : original_assignments) {
335 ss << assignment <<
" ";
338 ss <<
", new assignments: { ";
339 for (
const auto & assignment : new_assignments) {
340 ss << assignment <<
" ";
Contains the standardized input data along with basic functionality.
void compute_induced_cost(const GEDGraph &g, const GEDGraph &h, NodeMap &node_map) const
Computes the edit cost between two graphs induced by a node map.
double edge_cost(LabelID label1, LabelID label2) const
Returns edge relabeling, insertion, or deletion cost.
void as_relation(std::vector< Assignment > &relation) const
Constructs the representation as relation.
double node_cost(LabelID label1, LabelID label2) const
Returns node relabeling, insertion, or deletion cost.
const GEDData< UserNodeLabel, UserEdgeLabel > & ged_data_
The data on which the method is run.
NodeID head(EdgeID edge) const
Returns the head of an edge.
bool is_edge(NodeID tail, NodeID head) const
Checks if an edge exists.
GEDGraph::NodeID pre_image(GEDGraph::NodeID node) const
Returns pre-image of a node.
virtual void ls_set_default_options_()
Sets all options that are not among the ones shared by all derived classes of ged::LSBasedMethod to d...
virtual bool ls_parse_option_(const std::string &option, const std::string &arg)
Parses one option that is not among the ones shared by all derived classes of ged::LSBasedMethod.
double induced_cost() const
Returns the induced cost.
NodeID tail(EdgeID edge) const
Returns the tail of an edge.
LabelID get_node_label(NodeID node) const
Returns the label of a given node.
static NodeID dummy_node()
Returns a dummy node.
LabelID get_edge_label(EdgeID edge) const
Returns the label of a given edge.
double swap_cost(const GEDGraph &g, const GEDGraph &h, const NodeMap::Assignment &assignment_1, const NodeMap::Assignment &assignment_2, NodeMap &node_map) const
Computes the cost of swapping two assignments in a node map while leaving the node map unchanged...
virtual std::string ls_valid_options_string_() const
Returns string of all valid options that are not among the ones shared by all derived classes of ged:...
std::pair< incident_edge_iterator, incident_edge_iterator > incident_edges(NodeID node) const
Provides access to all incident edges of a node.
The normalized input graphs used by GEDLIB. All labels are integers.
void add_assignment(GEDGraph::NodeID i, GEDGraph::NodeID k)
Add node substitution, insertion, or deletion to the node map.
void set_induced_cost(double induced_cost)
Sets the induced cost of the node map.
constexpr LabelID dummy_label()
Returns a dummy label.
Computes an upper bound for general edit costs.
Global namespace for GEDLIB.
GEDGraph::NodeID image(GEDGraph::NodeID node) const
Returns image of a node.
virtual void ls_run_from_initial_solution_(const GEDGraph &g, const GEDGraph &h, double lower_bound, const NodeMap &initial_node_map, NodeMap &output_node_map) final
Runs the local search from an initial node map.
std::size_t NodeID
Internally used vertex ID type.