Skip to content
Snippets Groups Projects

Resolve "Learner1D's bound check algo in self.ask doesn't take self.data or self.pending_points"

Compare and
3 files
+ 112
34
Compare changes
  • Side-by-side
  • Inline
Files
3
@@ -287,44 +287,78 @@ class Learner1D(BaseLearner):
if n == 0:
return [], []
# Some temporary functions we are gonna need later in ask().
# xs is very similar to np.linspace but doesn't include the bounds
+5
def xs(x_left, x_right, n):
if n == 1:
# This is just an optimization
return []
else:
step = (x_right - x_left) / n
return [x_left + step * i for i in range(1, n)]
x_scale = self._scale[0]
def finite_loss(loss, xs):
# if the loss is infinite, return the distance between the two points
if math.isinf(loss):
return (xs[1] - xs[0]) / x_scale
return loss
# If the bounds have not been chosen yet, we choose them first.
missing_bounds = [b for b in self.bounds if b not in self.data
and b not in self.pending_points]
if missing_bounds:
loss_improvements = [np.inf] * n
# XXX: should check if points are present in self.data or self.pending_points
points = np.linspace(*self.bounds, n + 2 - len(missing_bounds)).tolist()
if len(missing_bounds) == 1:
points = points[1:] if missing_bounds[0] == self.bounds[1] else points[:-1]
if len(missing_bounds) >= n:
# shortcut as we do not need to find any more points
if add_data:
self.tell_many(missing_bounds[:n], itertools.repeat(None))
return missing_bounds[:n], [np.inf] * n
quals = [(-finite_loss(loss, x), x, 1)
for x, loss in self.losses_combined.items()]
# Add bound intervals to quals if bounds were missing
number_of_points_combined = len(self.data) + len(self.pending_points)
+3
if len(missing_bounds) == 0:
pass # perfect, do nothing
elif number_of_points_combined == 0:
# The only interval is the interval of the bounds
assert len(missing_bounds) == 2 # because no x is provided, all bounds are missing
quals.append((-finite_loss(np.inf, self.bounds), self.bounds, 1))
# XXX for performance we could shortcut to return linspace
else:
def xs(x_left, x_right, n):
if n == 1:
# This is just an optimization
return []
else:
step = (x_right - x_left) / n
return [x_left + step * i for i in range(1, n)]
# Calculate how many points belong to each interval.
x_scale = self._scale[0]
quals = [((-loss if not math.isinf(loss) else -(x[1] - x[0]) / x_scale, x, 1))
for x, loss in self.losses_combined.items()]
heapq.heapify(quals)
for point_number in range(n):
quality, x, n = quals[0]
if abs(x[1] - x[0]) / (n + 1) <= self._dx_eps:
# The interval is too small and should not be subdivided
quality = np.inf
heapq.heapreplace(quals, (quality * n / (n + 1), x, n + 1))
points = list(itertools.chain.from_iterable(
xs(*x, n) for quality, x, n in quals))
loss_improvements = list(itertools.chain.from_iterable(
itertools.repeat(-quality, n - 1)
for quality, x, n in quals))
# there is at least one intermediate point between the bounds
all_x_combined = list(self.data.keys()) + list(self.pending_points)
left_bound, right_bound = self.bounds
if left_bound in missing_bounds:
left_interval = (left_bound, np.min(all_x_combined))
quals.append((-finite_loss(np.inf, left_interval), left_interval, 1))
if right_bound in missing_bounds:
right_interval = (np.max(all_x_combined), right_bound)
quals.append((-finite_loss(np.inf, right_interval), right_interval, 1))
# Calculate how many points belong to each interval.
heapq.heapify(quals)
for _ in range(n - len(missing_bounds)):
quality, x, n = quals[0]
if abs(x[1] - x[0]) / (n + 1) <= self._dx_eps:
# The interval is too small and should not be subdivided
quality = np.inf
heapq.heapreplace(quals, (quality * n / (n + 1), x, n + 1))
points = list(itertools.chain.from_iterable(
xs(*x, n) for quality, x, n in quals))
loss_improvements = list(itertools.chain.from_iterable(
itertools.repeat(-quality, n - 1)
for quality, x, n in quals))
points = missing_bounds + points
loss_improvements = [np.inf] * len(missing_bounds) + loss_improvements
if add_data:
self.tell_many(points, itertools.repeat(None))
Loading