diff --git a/.gitmodules b/.gitmodules index 4653decc..940e1e27 100644 --- a/.gitmodules +++ b/.gitmodules @@ -43,3 +43,6 @@ [submodule "code/fastiota"] path = fastiota url = https://github.com/dnbaker/fastiota +[submodule "discreture"] + path = discreture + url = https://github.com/mraggi/discreture/ diff --git a/discreture b/discreture new file mode 160000 index 00000000..c90e9396 --- /dev/null +++ b/discreture @@ -0,0 +1 @@ +Subproject commit c90e9396aebc9162dabb43d059075837ed6f43a9 diff --git a/distmat b/distmat index c1535a47..53a3edb5 160000 --- a/distmat +++ b/distmat @@ -1 +1 @@ -Subproject commit c1535a47a299e4b140148ba7236ea366115df0c9 +Subproject commit 53a3edb5623c68383aa1024bcc687138d13da4b8 diff --git a/include/minocore/coreset/coreset.h b/include/minocore/coreset/coreset.h index d18eef54..ffe183b4 100644 --- a/include/minocore/coreset/coreset.h +++ b/include/minocore/coreset/coreset.h @@ -52,6 +52,7 @@ static const char *sm2str(SensitivityMethod sm) { } return "UNKNOWN"; } +using namespace std::literals; template struct IndexCoreset { @@ -65,6 +66,34 @@ struct IndexCoreset { size_t size() const {return indices_.size();} IndexCoreset(IndexCoreset &&o) = default; IndexCoreset(const IndexCoreset &o) = default; + void write(gzFile fp) const { + uint64_t n = size(); + if(gzwrite(fp, &n, sizeof(n)) != sizeof(n)) goto fail; + if(gzwrite(fp, indices_.data(), indices_.size() * sizeof(IT)) != int64_t(indices_.size() * sizeof(IT))) + goto fail; + if(gzwrite(fp, weights_.data(), weights_.size() * sizeof(FT)) != int64_t(weights_.size() * sizeof(FT))) + goto fail; + return; + fail: + throw std::runtime_error("Failed to write in "s + __PRETTY_FUNCTION__); + } + void write(std::FILE *fp) const { + uint64_t n = size(); + if(std::fwrite(&n, sizeof(n), 1, fp) != 1) goto fail; + if(std::fwrite(indices_.data(), sizeof(IT), indices_.size(), fp) != int64_t(indices_.size())) + goto fail; + if(std::fwrite(weights_.data(), sizeof(FT), weights_.size(), fp) != int64_t(weights_.size())) + goto fail; + return; + fail: + throw std::runtime_error("Failed to write in "s + __PRETTY_FUNCTION__); + } + void write(std::string path) const { + gzFile fp = gzopen(path.data(), "rb"); + if(!fp) throw std::runtime_error("Failed to open file in "s + __PRETTY_FUNCTION__); + write(fp); + gzclose(fp); + } void compact(bool shrink_to_fit=true) { // TODO: replace with hash map and compact std::map, uint32_t> m; @@ -205,6 +234,7 @@ struct CoresetSampler { gzclose(fp); } void write(gzFile fp) const { + if(fl_asn_ || fl_bicriteria_points_) throw std::runtime_error("Not implemented: serialization for FL coreset samplers"); uint64_t n = np_; gzwrite(fp, &n, sizeof(n)); #if VERBOSE_AF diff --git a/include/minocore/optim/lsearch.h b/include/minocore/optim/lsearch.h index 48c4a762..062ec82c 100644 --- a/include/minocore/optim/lsearch.h +++ b/include/minocore/optim/lsearch.h @@ -5,6 +5,7 @@ #include "minocore/util/oracle.h" #include "minocore/optim/kcenter.h" #include "pdqsort/pdqsort.h" +#include "discreture/include/discreture.hpp" #include /* @@ -18,27 +19,6 @@ namespace minocore { namespace graph { -namespace detail { - -template -void recursive_combinatorial_for_each(size_t nitems, unsigned r, T &ret, size_t npicks, const Functor &func) { - for(unsigned i = nitems; i >= r; i--) { - ret[r - 1] = i - 1; - if(r > 1) { - recursive_combinatorial_for_each(i - 1, r - 1, ret, npicks, func); - } else { - func(ret); - } - } -} - -} - -#if 0 -std::vector kcenter_matrix(const Mat &mat, RNG &rng, unsigned k) { -} - auto approx = kcenter_matrix(mat_, rng, k_); -#endif template struct ExhaustiveSearcher { @@ -52,17 +32,17 @@ struct ExhaustiveSearcher { blaze::SmallArray csol(k_); const size_t nr = mat_.rows(); size_t nchecked = 0; - detail::recursive_combinatorial_for_each(nr, k_, csol, k_, [&](const auto &sol) { - const double cost = blz::sum(blz::min(rows(mat_, sol BLAZE_CHECK_DEBUG))); + for(auto &&comb: discreture::combinations(nr, k_)) { + const double cost = blz::sum(blz::min(rows(mat_, comb.data(), comb.size()))); ++nchecked; if((nchecked & (nchecked - 1)) == 0) std::fprintf(stderr, "iteration %zu completed\n", nchecked); if(cost < current_cost_) { std::fprintf(stderr, "Swapping to new center set with new cost = %g on iteration %zu\n", cost, nchecked); current_cost_ = cost; - bestsol_ = sol; + std::copy(comb.data(), comb.data() + comb.size(), bestsol_.data()); } - }); + } std::fprintf(stderr, "Best result: %g. Total number of combinations checked: %zu\n", current_cost_, nchecked); } }; @@ -80,11 +60,18 @@ struct LocalKMedSearcher { const MatType &mat_; shared::flat_hash_set sol_; blz::DV assignments_; + blz::DV current_costs_; double current_cost_; double eps_, initial_cost_, init_cost_div_; IType k_; const size_t nr_, nc_; - bool best_improvement_; + double diffthresh_; + blz::DV ordering_; + uint32_t shuffle_:1; + uint32_t lazy_eval_:2; + // Set to 0 to avoid lazy search, 1 to only do local search, and 2 to do lazy search and then use exhaustive + uint32_t max_swap_n_:16; + // TODO: enable searches for multiswaps. // Constructors @@ -96,15 +83,17 @@ struct LocalKMedSearcher { } template> LocalKMedSearcher(const MatType &mat, unsigned k, double eps=1e-8, uint64_t seed=0, - bool best_improvement=false, const IndexContainer *wc=nullptr, double initdiv=0.): + const IndexContainer *wc=nullptr, double initdiv=0.): mat_(mat), assignments_(mat.columns(), 0), // center_indices_(k), //costs_(mat.columns(), std::numeric_limits::max()), //counts_(k), current_cost_(std::numeric_limits::max()), eps_(eps), - k_(k), nr_(mat.rows()), nc_(mat.columns()), best_improvement_(best_improvement) + k_(k), nr_(mat.rows()), nc_(mat.columns()), + ordering_(mat.rows()), shuffle_(true), lazy_eval_(false), max_swap_n_(1) { + std::iota(ordering_.begin(), ordering_.end(), 0); static_assert(std::is_integral_voperator[](0))>>, "index container must contain integral values"); sol_.reserve(k); init_cost_div_ = initdiv ? initdiv: double(mat.columns()); @@ -116,7 +105,6 @@ struct LocalKMedSearcher { sol_.clear(); sol_.insert(start, end); assignments_ = 0; - assign(); } template> @@ -125,14 +113,6 @@ struct LocalKMedSearcher { current_cost_ = std::numeric_limits::max(); wy::WyRand rng(seed); sol_.clear(); -#if 0 - if(wc) { - // Reweight - for(unsigned i = 0; i < wc->size(); ++i) { - column(mat_, i BLAZE_CHECK_DEBUG) *= wc->operator[](col); - } - } -#endif if(mat_.rows() <= k_) { for(unsigned i = 0; i < mat_.rows(); ++i) sol_.insert(i); @@ -187,7 +167,6 @@ struct LocalKMedSearcher { //std::fprintf(stderr, "used submatrix. sol size: %zu\n", sol_.size()); } } - assign(); } template @@ -213,14 +192,21 @@ struct LocalKMedSearcher { mat_.rows(), mat_.columns(), sol_.size(), k_); assert(sol_.size() == k_ || sol_.size() == mat_.rows()); DBG_ONLY(std::fprintf(stderr, "Initialized assignments at size %zu\n", assignments_.size());) - for(const auto center: sol_) { + auto it = sol_.begin(); + const auto eit = sol_.end(); + assignments_ = *it; + current_costs_ = row(mat_, *it); + while(++it != eit) { + auto center = *it; auto r = row(mat_, center BLAZE_CHECK_DEBUG); OMP_PFOR for(size_t ci = 0; ci < nc_; ++ci) { + auto asn = assignments_[ci]; if(const auto newcost = r[ci]; - newcost < mat_(assignments_[ci], ci)) + newcost < mat_(asn, ci)) { - assignments_[ci] = center; + current_costs_[ci] = newcost; + assignments_[ci] = center; } } } @@ -238,46 +224,73 @@ struct LocalKMedSearcher { cost = blaze::serial(blz::sum(blz::serial(blz::min(rows(mat_, as))))); } else cost = blz::sum(blz::min(rows(mat_, as))); return current_cost_ - cost; -#if 0 - //std::fprintf(stderr, "[%s] function starting: %u/%u\n", __PRETTY_FUNCTION__, newcenter, oldcenter); - assert(newcenter < mat_.rows()); - assert(oldcenter < mat_.rows()); - //std::fprintf(stderr, "Passed asserts\n"); - auto newr = row(mat_, newcenter BLAZE_CHECK_DEBUG); - //std::fprintf(stderr, "Got row: %zu\n", newr.size()); - assert(nc_ == newr.size()); - assert(assignments_.size() == mat_.columns()); - double potential_gain = 0.; -#define LOOP_CORE(ind) \ - do {\ - const auto asn = assignments_[ind];\ - assert(asn < nr_);\ - const auto old_cost = mat_(asn, ind);\ - if(asn == oldcenter) {\ - value_type newcost = newr[ind];\ - for(const auto ctr: sol_) {\ - if(ctr != oldcenter)\ - newcost = std::min(mat_(ctr, ind), newcost);\ - }\ - potential_gain += old_cost - newcost;\ - } else if(double nv = newr[ind]; nv < old_cost) {\ - potential_gain += old_cost - nv;\ - }\ - } while(0) + } + template + double evaluate_multiswap(const IType *newcenter, const IType *oldcenter, bool single_threaded=false) const { + blz::SmallArray as(sol_.begin(), sol_.end()); + for(size_t i = 0; i < N; ++i) { + *std::find(as.begin(), as.end(), oldcenter[i]) = newcenter[i]; + } + double cost; + if(single_threaded) { + cost = blaze::serial(blz::sum(blz::serial(blz::min(rows(mat_, as))))); + } else + cost = blz::sum(blz::min(rows(mat_, as))); + return current_cost_ - cost; + } + template + double evaluate_multiswap_rt(const IndexType *newcenter, const IndexType *oldcenter, size_t N, bool single_threaded=false) const { + blz::SmallArray as(sol_.begin(), sol_.end()); + for(size_t i = 0; i < N; ++i) { + *std::find(as.begin(), as.end(), oldcenter[i]) = newcenter[i]; + } + shared::sort(as.begin(), as.end()); + double cost; if(single_threaded) { - for(size_t i = 0; i < nc_; ++i) { - LOOP_CORE(i); + cost = blaze::serial(blz::sum(blz::serial(blz::min(rows(mat_, as))))); + } else + cost = blz::sum(blz::min(rows(mat_, as))); + return current_cost_ - cost; + } + + template + double lazy_evaluate_multiswap(const IType *newcenters, const IType *oldcenters) const { + // Instead of performing the full recalculation, do lazy calculation. + // + std::vector tmp(sol_.begin(), sol_.end()); + for(unsigned i = 0; i < N; ++i) + tmp.erase(std::find(tmp.begin(), tmp.end(), oldcenters[i])); + std::sort(tmp.begin(), tmp.end()); + // Instead of performing the full recalculation, do lazy calculation. + if(current_costs_.size() != nc_) { // If not calculated, calculate + auto it = sol_.begin(); + OMP_CRITICAL + { + current_costs_ = row(mat_, *it BLAZE_CHECK_DEBUG); } - } else { - OMP_PRAGMA("omp parallel for reduction(+:potential_gain)") - for(size_t i = 0; i < nc_; ++i) { - LOOP_CORE(i); + while(++it != sol_.end()) { + current_costs_ = blz::min(current_costs_, row(mat_, *it BLAZE_CHECK_DEBUG)); } } -#undef LOOP_CORE - return potential_gain; + blz::DV newptr = blz::min(rows(mat_, newcenters, N)); + blz::DV oldptr = blz::min(rows(mat_, oldcenters, N)); + double diff = 0.; +#ifdef _OPENMP + _Pragma("omp parallel for reduction(+:diff)") #endif + for(size_t i = 0; i < nc_; ++i) { + auto ccost = current_costs_[i]; + if(newptr[i] < ccost) { + auto sub = ccost - newptr[i]; + diff += sub; + } else if(ccost == oldptr[i]) { + auto oldbest = blz::min(blz::elements(blz::column(mat_, i), tmp.data(), tmp.size())); + auto sub = ccost - std::min(oldbest, newptr[i]); + diff += sub; + } + } + return diff; } // Getters @@ -285,70 +298,140 @@ struct LocalKMedSearcher { return k_; } - void run() { - if(mat_.rows() < k_) return; - //const double diffthresh = 0.; - const double diffthresh = initial_cost_ / k_ * eps_; - std::fprintf(stderr, "diffthresh: %f\n", diffthresh); + void run_lazy() { +#if 0 + shared::flat_hash_map> current_assignments; + for(size_t i = 0; i < assignments_.size(); ++i) { + current_assignments[assignments_[i]].push_back(i); + } +#endif size_t total = 0; - { - double current_best; - IType current_best_index, current_best_center; - next: - if(best_improvement_) { - current_best = std::numeric_limits::min(); - current_best_index = -1, current_best_center = -1; - for(const auto oldcenter: sol_) { - OMP_PFOR - for(size_t pi = 0; pi < nr_; ++pi) { - if(sol_.find(pi) == sol_.end()) { - if(const auto val = evaluate_swap(pi, oldcenter, true); - val > diffthresh && val > current_best) - { - OMP_CRITICAL - { - if(val > current_best) { - current_best = val; - current_best_index = pi; - current_best_center = oldcenter; - } - current_cost_ -= val; - } - std::fprintf(stderr, "[Best improvement] Swapping %zu for %u. Swap number %zu. Current cost: %g. Improvement: %g\n", pi, oldcenter, total + 1, current_cost_, val); - } - } + std::vector newindices(sol_.begin(), sol_.end()); + next: + for(const auto oldcenter: sol_) { + std::swap(*std::find(newindices.begin(), newindices.end(), oldcenter), newindices.back()); + if(shuffle_) { + wy::WyRand rng(total); + std::shuffle(ordering_.begin(), ordering_.end(), rng); + } + // Make a vector with the original solution, but replace the old value with the new value + for(size_t pi = 0; pi < nr_; ++pi) { + auto potential_index = ordering_[pi]; + if(sol_.find(potential_index) != sol_.end()) continue; + newindices.back() = potential_index; + assert(std::find(newindices.begin(), newindices.end(), oldcenter) == newindices.end()); + double val = 0.; + auto newptr = row(mat_, potential_index); +#ifdef _OPENMP + #pragma omp parallel for reduction(+:val) +#endif + for(size_t i = 0; i < nc_; ++i) { + auto oldcost = current_costs_[i]; + if(newptr[i] < oldcost) { + auto diff = oldcost - newptr[i]; + val += diff; + } else if(assignments_[i] == oldcenter) { + auto mincost = blz::min(blz::elements(blz::column(mat_, i), newindices.data(), newindices.size())); + auto diff = oldcost - mincost; + val += diff; } } - if(current_best_index != IType(-1)) { - sol_.erase(current_best_center); - sol_.insert(current_best_index); +#ifndef NDEBUG + auto v = evaluate_swap(potential_index, oldcenter); + //assert(std::abs(v - val) <= .5 * std::abs(std::max(v, val)) || !std::fprintf(stderr, "Manual: %g. Lazy: %g\n", v, val)); + assert(sol_.size() == k_); +#endif + // Only calculate exhaustively if the lazy form returns yes. + if(val > diffthresh_ && (val = evaluate_swap(potential_index, oldcenter) > diffthresh_)) { + assert(sol_.size() == k_); + sol_.erase(oldcenter); + sol_.insert(potential_index); + assert(sol_.size() == k_); + assign(); + //current_cost_ = blz::sum(current_costs_); ++total; + std::fprintf(stderr, "Swap number %zu updated with delta %g to new cost with cost %0.12g\n", total, val, current_cost_); goto next; - //diffthresh = current_cost_ / k_ * eps_; } - } else { - for(const auto oldcenter: sol_) { - for(size_t pi = 0; pi < nr_; ++pi) { - if(sol_.find(pi) == sol_.end()) { - if(const auto val = evaluate_swap(pi, oldcenter); - val > diffthresh) { -#ifndef NDEBUG - std::fprintf(stderr, "Swapping %zu for %u. Swap number %zu. Current cost: %g. Improvement: %g. Threshold: %g.\n", pi, oldcenter, total + 1, current_cost_, val, diffthresh); -#endif - sol_.erase(oldcenter); - sol_.insert(pi); - ++total; - current_cost_ -= val; - std::fprintf(stderr, "Swap number %zu with cost %0.12g\n", total, current_cost_); - goto next; - } - } + } + } + std::fprintf(stderr, "Finished in %zu swaps by exhausting all potential improvements. Final cost: %f\n", + total, current_cost_); + } + + void run_multi(unsigned nswap=1) { + if(mat_.rows() <= k_) return; + if(nswap == 1) { + run(); + return; + } + if(nswap >= k_) throw std::runtime_error("nswap >= k_"); + assign(); + const double diffthresh = initial_cost_ / k_ * eps_; + diffthresh_ = diffthresh; + next: + { + blz::DV csol(sol_.size()); + std::copy(sol_.begin(), sol_.end(), csol.data()); + blz::DV swap_in(nc_ - sol_.size()); + blz::DV inargs(nswap), outargs(nswap); + for(auto &&swap_out_comb: discreture::combinations(csol.size(), nswap)) { + for(auto &&swap_in_comb: discreture::combinations(swap_in.size(), nswap)) { + auto v = evaluate_multiswap_rt(swap_in_comb.data(), swap_out_comb.data(), nswap); + if(v >= diffthresh_) { + for(auto v: swap_out_comb) sol_.erase(v); + sol_.insert(swap_in_comb.begin(), swap_in_comb.end()); + current_cost_ -= v; + goto next; } } } } + } + void run() { + assign(); + const double diffthresh = initial_cost_ / k_ * eps_; + diffthresh_ = diffthresh; + if(mat_.rows() <= k_) return; + if(lazy_eval_) { + run_lazy(); + if(lazy_eval_ == 2) + return; + // Otherwise, running exhaustive local search after to be sure. + } + //const double diffthresh = 0.; + std::fprintf(stderr, "diffthresh: %f\n", diffthresh); + size_t total = 0; + next: + for(const auto oldcenter: sol_) { + if(shuffle_) { + wy::WyRand rng(total); + std::shuffle(ordering_.begin(), ordering_.end(), rng); + } + std::vector newindices(sol_.begin(), sol_.end()); + for(size_t pi = 0; pi < nr_; ++pi) { + size_t potential_index = ordering_[pi]; + if(sol_.find(potential_index) != sol_.end()) continue; + if(const auto val = evaluate_swap(potential_index, oldcenter, true); + val > diffthresh) { +#ifndef NDEBUG + std::fprintf(stderr, "Swapping %zu for %u. Swap number %zu. Current cost: %g. Improvement: %g. Threshold: %g.\n", potential_index, oldcenter, total + 1, current_cost_, val, diffthresh); +#endif + sol_.erase(oldcenter); + sol_.insert(potential_index); + ++total; + current_cost_ -= val; + std::fprintf(stderr, "Swap number %zu with cost %0.12g\n", total, current_cost_); + goto next; + } + } + } std::fprintf(stderr, "Finished in %zu swaps by exhausting all potential improvements. Final cost: %f\n", total, current_cost_); + if(max_swap_n_ > 1) { + std::fprintf(stderr, "max_swap_n_ %u set. Searching multiswaps\n", max_swap_n_); + run_multi(max_swap_n_); + } } void exhaustive_manual_check() { const std::vector csol(sol_.begin(), sol_.end()); @@ -388,9 +471,9 @@ struct LocalKMedSearcher { }; template> -auto make_kmed_lsearcher(const Mat &mat, unsigned k, double eps=0.01, uint64_t seed=0, bool best_improvement=false, +auto make_kmed_lsearcher(const Mat &mat, unsigned k, double eps=0.01, uint64_t seed=0, const IndexContainer *wc=nullptr, double initdiv=0.) { - return LocalKMedSearcher(mat, k, eps, seed, best_improvement, wc, initdiv); + return LocalKMedSearcher(mat, k, eps, seed, wc, initdiv); } } // graph diff --git a/include/minocore/util/timer.h b/include/minocore/util/timer.h index 3bd697e0..1bc0da53 100644 --- a/include/minocore/util/timer.h +++ b/include/minocore/util/timer.h @@ -13,7 +13,7 @@ using hrc = std::chrono::high_resolution_clock; template static inline uint32_t timediff2ms(std::chrono::time_point start, std::chrono::time_point stop) { if(stop < start) std::swap(stop, start); - return static_cast(static_cast((stop - start).count()) / 1000000); + return std::chrono::duration(stop - start).count(); } struct Timer { diff --git a/include/minocore/wip/streaming.h b/include/minocore/wip/streaming.h index 791e2896..90dd8861 100644 --- a/include/minocore/wip/streaming.h +++ b/include/minocore/wip/streaming.h @@ -21,17 +21,14 @@ namespace streaming { template>> struct UniformWeightIterator { - //size_t nsteps_ = 0; FT operator*() const { return static_cast(1); } UniformWeightIterator &operator++() { - //++nsteps_; return *this; } UniformWeightIterator operator++(int) { UniformWeightIterator ret(*this); - //++nsteps_; return ret; } }; diff --git a/network_simplex/network_simplex_simple.h b/network_simplex/network_simplex_simple.h index b7b96b77..e1c5d996 100644 --- a/network_simplex/network_simplex_simple.h +++ b/network_simplex/network_simplex_simple.h @@ -1302,7 +1302,7 @@ namespace lemon { } else { // Handle the case when old_rev_thread equals to v_in // (it also means that join and v_out coincide) - int thread_continue = old_rev_thread == v_in ? + int thread_continue = old_rev_thread == static_cast(v_in) ? _thread[old_last_succ] : _thread[v_in]; // Update _thread and _parent along the stem nodes (i.e. the nodes @@ -1315,7 +1315,7 @@ namespace lemon { _thread[v_in] = u_in; _dirty_revs.clear(); _dirty_revs.push_back(v_in); - while (stem != u_out) { + while (stem != static_cast(u_out)) { // Insert the next stem node into the thread list next_stem = _parent[stem]; _thread[last] = next_stem; @@ -1357,7 +1357,7 @@ namespace lemon { // Update _pred, _pred_dir, _last_succ and _succ_num for the // stem nodes from u_out to u_in int tmp_sc = 0, tmp_ls = _last_succ[u_out]; - for (int u = u_out, p = _parent[u]; u != u_in; u = p, p = _parent[u]) { + for (int u = u_out, p = _parent[u]; u != static_cast(u_in); u = p, p = _parent[u]) { _pred[u] = _pred[p]; _forward[u] = !_forward[p]; tmp_sc += _succ_num[u] - _succ_num[p]; @@ -1365,19 +1365,19 @@ namespace lemon { _last_succ[p] = tmp_ls; } _pred[u_in] = in_arc; - _forward[u_in] = (u_in == _source[in_arc]); + _forward[u_in] = (static_cast(u_in) == _source[in_arc]); _succ_num[u_in] = old_succ_num; } // Update _last_succ from v_in towards the root - int up_limit_out = _last_succ[join] == v_in ? join : -1; + int up_limit_out = static_cast(_last_succ[join]) == v_in ? join : -1; int last_succ_out = _last_succ[u_out]; for (int u = v_in; u != -1 && _last_succ[u] == v_in; u = _parent[u]) { _last_succ[u] = last_succ_out; } // Update _last_succ from v_out towards the root - if (join != old_rev_thread && v_in != old_rev_thread) { + if (static_cast(join) != old_rev_thread && static_cast(v_in) != old_rev_thread) { for (int u = v_out; u != up_limit_out && _last_succ[u] == old_last_succ; u = _parent[u]) { _last_succ[u] = old_rev_thread; @@ -1390,11 +1390,11 @@ namespace lemon { } // Update _succ_num from v_in to join - for (int u = v_in; u != join; u = _parent[u]) { + for (int u = v_in; u != static_cast(join); u = _parent[u]) { _succ_num[u] += old_succ_num; } // Update _succ_num from v_out to join - for (int u = v_out; u != join; u = _parent[u]) { + for (int u = v_out; u != static_cast(join); u = _parent[u]) { _succ_num[u] -= old_succ_num; } } diff --git a/src/kzclustexp.cpp b/src/kzclustexp.cpp index 1099bc6d..eb2ca200 100644 --- a/src/kzclustexp.cpp +++ b/src/kzclustexp.cpp @@ -132,7 +132,7 @@ void emit_coreset_optimization_runtime(Samp &sampler, unsigned k, double z, Grap }; t.start(); if(!skip_vxs) { - auto vxs_lsearcher = make_kmed_lsearcher(distances, k, 1e-2, rng(), false, &cs.indices_, blaze::sum(cs.weights_)); + auto vxs_lsearcher = make_kmed_lsearcher(distances, k, 1e-2, rng(), &cs.indices_, blaze::sum(cs.weights_)); vxs_lsearcher.run(); std::fprintf(stderr, "optimizing over vxs: %zu/%zu. cs weight size: %zu\n", distances.rows(), distances.columns(), cs.weights_.size()); std::vector solution(vxs_lsearcher.sol_.begin(), vxs_lsearcher.sol_.end()); @@ -151,7 +151,7 @@ void emit_coreset_optimization_runtime(Samp &sampler, unsigned k, double z, Grap t.reset(); t.start(); sqdistances = blaze::rows(distances, cs.indices_.data(), cs.indices_.size()); //sqdistances = blaze::rows(distances, cs.indices_.data(), cs.indices_.size()); - auto sxs_lsearcher = make_kmed_lsearcher(sqdistances, k, 1e-2, rng(), false, static_cast *>(nullptr), blaze::sum(cs.weights_)); + auto sxs_lsearcher = make_kmed_lsearcher(sqdistances, k, 1e-2, rng(), static_cast *>(nullptr), blaze::sum(cs.weights_)); sxs_lsearcher.run(); std::vector solution(sxs_lsearcher.sol_.begin(), sxs_lsearcher.sol_.end()); for(auto &i: solution) { @@ -392,7 +392,6 @@ int main(int argc, char **argv) { bool use_thorup_d = true, use_thorup_iterative = false; unsigned testing_num_centersets = 500; size_t rammax = 16uLL << 30; - bool best_improvement = false; bool local_search_all_vertices = false; unsigned coreset_testing_num_iters = 5; uint64_t seed = std::accumulate(argv, argv + argc, uint64_t(0), @@ -422,7 +421,7 @@ int main(int argc, char **argv) { case 'z': z = std::atof(optarg); break; case 'L': local_search_all_vertices = true; break; case 'r': rectangular = true; break; - case 'b': best_improvement = true; break; + case 'b': std::cerr << "best improvement has been removed.\n"; break; case 'R': seed = std::strtoull(optarg, nullptr, 10); break; case 'M': rammax = str2nbytes(optarg); break; case 'D': use_thorup_d = false; break; @@ -629,7 +628,7 @@ int main(int argc, char **argv) { // Perform Thorup sample before JV method. timer.restart("local search:"); - auto lsearcher = make_kmed_lsearcher(dm, k, eps, seed * seed + seed, best_improvement, bbox_vertices_ptr, x_size); + auto lsearcher = make_kmed_lsearcher(dm, k, eps, seed * seed + seed, bbox_vertices_ptr, x_size); lsearcher.run(); timer.report(); if(dm.rows() < 100 && k < 6) {