55 Assert(strategy, ExcMessage(
"No strategy selected"));
56 Assert(!source_points.empty(), ExcMessage(
"Source measure not set"));
57 Assert(!target_points.empty(), ExcMessage(
"Target measure not set"));
58 Assert(transport_potential.size() > 0, ExcMessage(
"Transport potential not set"));
60 strategy->compute_map(distance_function, source_points, source_density,
61 target_points, target_density,
62 transport_potential, epsilon,
101 const std::function<
double(
const Point<spacedim>&,
const Point<spacedim>&)> distance_function,
102 const std::vector<Point<spacedim>>& source_points,
103 const std::vector<double>& source_density,
104 const std::vector<Point<spacedim>>& target_points,
105 const std::vector<double>& target_density,
106 const Vector<double>& potential,
107 const double regularization_param,
108 const double truncation_radius)
110 using IndexedPoint = std::pair<Point<spacedim>, std::size_t>;
111 using RTreeParams = boost::geometry::index::rstar<8>;
112 using RTree = boost::geometry::index::rtree<IndexedPoint, RTreeParams>;
115 std::vector<IndexedPoint> indexed_points;
116 indexed_points.reserve(target_points.size());
117 for (std::size_t i = 0; i < target_points.size(); ++i) {
118 indexed_points.emplace_back(target_points[i], i);
120 RTree target_rtree(indexed_points.begin(), indexed_points.end());
123 this->mapped_points.resize(source_points.size());
124 this->transport_density.resize(source_points.size());
127 this->source_points = source_points;
130 const bool use_truncation = (truncation_radius > 0.0);
132 for (std::size_t i = 0; i < source_points.size(); ++i) {
133 const Point<spacedim>& x = source_points[i];
134 double max_score = -std::numeric_limits<double>::infinity();
135 std::size_t best_idx = 0;
138 std::vector<IndexedPoint> candidates;
140 if (use_truncation) {
143 boost::geometry::index::satisfies([&x, &distance_function, truncation_radius](
const IndexedPoint& p) {
144 return distance_function(x, p.first) < truncation_radius;
146 std::back_inserter(candidates)
150 if (candidates.empty()) {
151 target_rtree.query(boost::geometry::index::nearest(x, 1), std::back_inserter(candidates));
155 candidates.reserve(target_points.size());
156 for (std::size_t j = 0; j < target_points.size(); ++j) {
157 candidates.push_back(indexed_points[j]);
162 for (
const auto& candidate : candidates) {
163 const Point<spacedim>& y = candidate.first;
164 const std::size_t j = candidate.second;
167 double squared_dist = std::pow(distance_function(x, y), 2);
170 double log_term = 0.0;
171 if (target_density[j] > 0) {
172 log_term = regularization_param * std::log(target_density[j]);
175 log_term = -std::numeric_limits<double>::infinity();
178 double score = potential[j] - 0.5 * squared_dist + log_term;
180 if (score > max_score) {
186 this->mapped_points[i] = target_points[best_idx];
187 this->transport_density[i] = source_density[i];
221 const std::function<
double(
const Point<spacedim>&,
const Point<spacedim>&)> distance_function,
222 const std::vector<Point<spacedim>>& source_points,
223 const std::vector<double>& source_density,
224 const std::vector<Point<spacedim>>& target_points,
225 const std::vector<double>& target_density,
226 const Vector<double>& potential,
227 const double regularization_param,
228 const double truncation_radius)
230 using IndexedPoint = std::pair<Point<spacedim>, std::size_t>;
231 using RTreeParams = boost::geometry::index::rstar<8>;
232 using RTree = boost::geometry::index::rtree<IndexedPoint, RTreeParams>;
235 std::vector<IndexedPoint> indexed_points;
236 indexed_points.reserve(target_points.size());
237 for (std::size_t i = 0; i < target_points.size(); ++i) {
238 indexed_points.emplace_back(target_points[i], i);
240 RTree target_rtree(indexed_points.begin(), indexed_points.end());
242 this->mapped_points.resize(source_points.size());
243 this->transport_density.resize(source_points.size());
246 this->source_points = source_points;
249 const bool use_truncation = (truncation_radius > 0.0);
252 for (std::size_t i = 0; i < source_points.size(); ++i) {
253 const Point<spacedim>& x = source_points[i];
254 Point<spacedim> weighted_sum;
257 std::vector<IndexedPoint> candidates;
259 if (use_truncation) {
262 boost::geometry::index::satisfies([&x, &distance_function, truncation_radius](
const IndexedPoint& p) {
263 return distance_function(x, p.first) < truncation_radius;
265 std::back_inserter(candidates)
269 if (candidates.empty()) {
270 target_rtree.query(boost::geometry::index::nearest(x, 1), std::back_inserter(candidates));
271 const Point<spacedim>& nearest = candidates[0].first;
272 this->mapped_points[i] = nearest;
273 this->transport_density[i] = source_density[i];
278 candidates.reserve(target_points.size());
279 for (std::size_t j = 0; j < target_points.size(); ++j) {
280 candidates.push_back(indexed_points[j]);
286 std::vector<double> exponent_terms;
287 exponent_terms.reserve(candidates.size());
288 double max_exponent = -std::numeric_limits<double>::infinity();
290 for (
const auto& candidate : candidates) {
291 const Point<spacedim>& y = candidate.first;
292 const std::size_t j = candidate.second;
294 double squared_dist = std::pow(distance_function(x, y), 2);
295 double exponent = (potential[j] - 0.5 * squared_dist) / regularization_param;
297 exponent_terms.push_back(exponent);
298 max_exponent = std::max(max_exponent, exponent);
302 double sum_exp = 0.0;
303 for (std::size_t k = 0; k < candidates.size(); ++k) {
304 const auto& candidate = candidates[k];
305 const Point<spacedim>& y = candidate.first;
306 const std::size_t j = candidate.second;
309 double stable_exp = std::exp(exponent_terms[k] - max_exponent);
310 double weight = target_density[j] * stable_exp;
312 weighted_sum += weight * y;
318 this->mapped_points[i] = weighted_sum / sum_exp;
321 std::vector<IndexedPoint> nearest;
322 target_rtree.query(boost::geometry::index::nearest(x, 1), std::back_inserter(nearest));
323 this->mapped_points[i] = nearest[0].first;
326 this->transport_density[i] = source_density[i];
void compute_map(const std::function< double(const Point< spacedim > &, const Point< spacedim > &)> distance_function, const std::vector< Point< spacedim > > &source_points, const std::vector< double > &source_density, const std::vector< Point< spacedim > > &target_points, const std::vector< double > &target_density, const Vector< double > &potential, const double regularization_param, const double truncation_radius) override
Computes the transport map.
void compute_map(const std::function< double(const Point< spacedim > &, const Point< spacedim > &)> distance_function, const std::vector< Point< spacedim > > &source_points, const std::vector< double > &source_density, const std::vector< Point< spacedim > > &target_points, const std::vector< double > &target_density, const Vector< double > &potential, const double regularization_param, const double truncation_radius) override
Computes the transport map.