From f56257a80e96b7abdc6b937eedf21a6796b83ca1 Mon Sep 17 00:00:00 2001 From: Bas Nijholt Date: Wed, 9 Oct 2019 13:16:28 +0200 Subject: [PATCH] 2D: add triangle_loss --- adaptive/learner/learner2D.py | 40 +++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/adaptive/learner/learner2D.py b/adaptive/learner/learner2D.py index 91f1a0082..1fe5cfd19 100644 --- a/adaptive/learner/learner2D.py +++ b/adaptive/learner/learner2D.py @@ -9,6 +9,7 @@ from scipy import interpolate from adaptive.learner.base_learner import BaseLearner +from adaptive.learner.triangulation import simplex_volume_in_embedding from adaptive.notebook_integration import ensure_holoviews from adaptive.utils import cache_latest @@ -212,6 +213,45 @@ def choose_point_in_triangle(triangle, max_badness): return point +def triangle_loss(ip): + r"""Computes the average of the volumes of the simplex combined with each + neighbouring point. + + Parameters + ---------- + ip : `scipy.interpolate.LinearNDInterpolator` instance + + Returns + ------- + triangle_loss : list + The mean volume per triangle. + + Notes + ----- + This loss function is *extremely* slow. It is here because it gives the + same result as the `adaptive.LearnerND`\s + `~adaptive.learner.learnerND.triangle_loss`. + """ + tri = ip.tri + + def get_neighbors(i, ip): + n = np.array([tri.simplices[n] for n in tri.neighbors[i] if n != -1]) + # remove the vertices that are in the simplex + c = np.setdiff1d(n.reshape(-1), tri.simplices[i]) + return np.concatenate((tri.points[c], ip.values[c]), axis=-1) + + simplices = np.concatenate( + [tri.points[tri.simplices], ip.values[tri.simplices]], axis=-1 + ) + neighbors = [get_neighbors(i, ip) for i in range(len(tri.simplices))] + + return [ + sum(simplex_volume_in_embedding(np.vstack([simplex, n])) for n in neighbors[i]) + / len(neighbors[i]) + for i, simplex in enumerate(simplices) + ] + + class Learner2D(BaseLearner): """Learns and predicts a function 'f: ℝ^2 → ℝ^N'.