-
Notifications
You must be signed in to change notification settings - Fork 6
Expand file tree
/
Copy pathjv.h
More file actions
104 lines (97 loc) · 3.52 KB
/
Copy pathjv.h
File metadata and controls
104 lines (97 loc) · 3.52 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
#pragma once
#ifndef JAIN_VAZIRANI_H__
#define JAIN_VAZIRANI_H__
#include <queue>
#include <vector>
#include <iostream>
#include "minicore/graph/graph.h"
#include "minicore/util/blaze_adaptor.h"
#include "minicore/optim/jv_solver.h"
/*
* Implementation of method of Jain-Vazirani for Metric k-median clustering
* on graphs.
*
*
bibtex:
@article{Jain:2001:AAM:375827.375845,
author = {Jain, Kamal and Vazirani, Vijay V.},
title = {Approximation Algorithms for Metric Facility Location and k-Median Problems Using the Primal-dual Schema and Lagrangian Relaxation},
journal = {J. ACM},
issue_date = {March 2001},
volume = {48},
number = {2},
month = mar,
year = {2001},
issn = {0004-5411},
pages = {274--296},
numpages = {23},
url = {http://doi.acm.org/10.1145/375827.375845},
doi = {10.1145/375827.375845},
acmid = {375845},
publisher = {ACM},
address = {New York, NY, USA},
keywords = {k-median problem, Lagrangian relaxation, approximation algorithms, facility location problem, linear prminicoreramming},
}
*/
namespace minicore {
template<typename Graph, typename Mat>
void fill_cand_distance_mat(const Graph &x, Mat &mat, const std::vector<typename Graph::vertex_descriptor> &candidates) {
assert(mat.rows() == candidates.size());
assert(mat.columns() == x.num_vertices());
OMP_PRAGMA("omp parallel for")
for(size_t i = 0; i < candidates.size(); ++i) {
auto edge = candidates[i];
auto r = row(mat, i);
assert(r.size() == x.num_vertices());
boost::dijkstra_shortest_paths(x, edge,
boost::distance_map(&r[0]));
if(r[0] == std::numeric_limits<float>::max()) {
throw std::runtime_error("This is probably not connected");
}
// Now the row c(r, i) has the distances from candidate facility candidates[i] to
// all nodes.
}
}
/*
*
* jain_vazirani_ufl is the uncapacitated facility location proble
* from JV, where a total_cost is the budget allocated.
* This forms the inner loop of a binary search
* for the k-median problem.
* The k-median solution (below) is the final step
* in the Mikkel Thorup 12-approximate solution
* to the metric k-median problem.
* Implemented with additional commentary from https://www.cs.cmu.edu/~anupamg/adv-approx/lecture5.pdf
*/
template<typename Graph>
std::vector<typename Graph::vertex_descriptor>
jain_vazirani_kmedian(Graph &x,
const std::vector<typename Graph::vertex_descriptor> &candidates,
unsigned k,
blaze::DynamicMatrix<float> *costsmat=nullptr)
{
// candidates consists of a vector of potential facility centers.
//using Edge = typename Graph::edge_descriptor;
const size_t n = x.num_vertices();
size_t nf = candidates.size();
std::unique_ptr<blaze::DynamicMatrix<float>> optr;
if(costsmat) {
costsmat->resize(nf, n);
} else {
optr.reset(new blaze::DynamicMatrix<float>(nf, n, 0.));
}
blaze::DynamicMatrix<float> &c(*(costsmat ? costsmat: optr.get()));
fill_cand_distance_mat(x, c, candidates);
#if VERBOSE_AF
std::cerr << "cost matrix: " << c << '\n';
#endif
// maxcost = (maxcostedgecost * num_cities)
jv::JVSolver<blaze::DynamicMatrix<float>> jvs(c);
auto [sol, solasn] = jvs.kmedian(k);
std::vector<typename Graph::vertex_descriptor> ret(sol.size());
for(size_t i = 0; i < sol.size(); ++i)
ret[i] = candidates[sol[i]];
return ret;
} // jain_vazirani_ufl
} // namespace minicore
#endif /* JAIN_VAZIRANI_H__ */