#include #include #include #include "GeomPerfectMatching.h" #include "GPMkdtree.h" #include "../timer.h" GeomPerfectMatching::REAL GeomPerfectMatching::SolveComplete() { if (node_num != node_num_max) { printf("ComputeCost() cannot be called before all points have been added!\n"); exit(1); } PointId p, q; int e = 0, E = node_num*(node_num-1)/2; PerfectMatching* pm = new PerfectMatching(node_num, E); for (p=0; pAddEdge(p, q, Dist(p, q)); } } pm->options = options; pm->Solve(); for (p=0; pGetSolution(e++)) { matching[p] = q; matching[q] = p; } } } delete pm; return ComputeCost(matching); } GeomPerfectMatching::REAL GeomPerfectMatching::Solve() { double start_time = get_time(); double perfect_matching_time = 0; double negative_edges_time = 0; if (options.verbose) { printf("starting geometric matching with %d points\n", node_num); fflush(stdout); } PointId p, q; Edge* e; int _e; int iter; bool success = false; PerfectMatching* pm = NULL; GPMKDTree* kd_tree; double init_matching_time = get_time(); if (gpm_options.init_Delaunay) InitDelaunay(); if (gpm_options.init_KNN > 0) InitKNN(gpm_options.init_KNN); if (gpm_options.init_greedy) CompleteInitialMatching(); init_matching_time = get_time() - init_matching_time; graph_update_time = 0; int iter_max = gpm_options.iter_max; for (iter=0; iter_max<=0 || iterStartUpdate(); for (p=0; pGetTwiceSum(p); if ( ((REAL)1 / 2) == 0 && ((PerfectMatching::REAL)1 / 2) != 0 ) sums[p] = (REAL)ceil((double)s); else sums[p] = (REAL)s; } if (options.verbose) { printf("building kd_tree..."); fflush(stdout); } { kd_tree = new GPMKDTree(DIM+1, node_num, coords, this); } if (options.verbose) { printf(" done. Now adding negative edges:\n "); fflush(stdout); } for (p=0; pnext[0]) nodes[e->head[0]].is_marked = 1; for (e=nodes[p].first[1]; e; e=e->next[1]) nodes[e->head[1]].is_marked = 1; kd_tree->AddNegativeEdges(p, pm); for (e=nodes[p].first[0]; e; e=e->next[0]) nodes[e->head[0]].is_marked = 0; for (e=nodes[p].first[1]; e; e=e->next[1]) nodes[e->head[1]].is_marked = 0; } delete kd_tree; //if (edge_num - edge_num0 > node_num / 32) if ( 0 ) // always reuse previous computation { delete pm; pm = NULL; } else { pm->FinishUpdate(); if (edge_num0 == edge_num) success = true; } if (options.verbose) { printf("\ndone (%d edges added)\n", edge_num-edge_num0); fflush(stdout); } negative_edges_time += get_time() - negative_edges_start_time; } if (!pm) { int E = 5*node_num; if (E < 5*edge_num/4) E = 5*edge_num/4; pm = new PerfectMatching(node_num, E); for (e=edges->ScanFirst(); e; e=edges->ScanNext()) { p = e->head[1]; q = e->head[0]; pm->AddEdge(p, q, Dist(p, q)); } } if (options.verbose) printf("iter %d: ", iter+1); pm->options = options; double perfect_matching_start = get_time(); pm->Solve(); perfect_matching_time += get_time() - perfect_matching_start; if (success) break; } for (_e=0, e=edges->ScanFirst(); e; _e++, e=edges->ScanNext()) { if (pm->GetSolution(_e)) { p = e->head[1]; q = e->head[0]; matching[p] = q; matching[q] = p; } } delete pm; REAL cost = ComputeCost(matching); if (options.verbose) { printf("geometric matching finished [%.3f secs]. cost=%.1f \n", get_time()-start_time, (double)cost); printf(" selecting initial edges: [%.3f secs], perfect matching: [%.3f secs]\n", init_matching_time, perfect_matching_time); printf(" pricing: [%.3f secs] including graph updates: [%.3f secs]\n", negative_edges_time, graph_update_time); fflush(stdout); } return cost; }