Commit bb9c8933 authored by Mathias Diez's avatar Mathias Diez Committed by Anton Akhmerov
Browse files

Added Oracle, initially tested, but mostlikely not very good performance. Not...

Added Oracle, initially tested, but mostlikely not very good performance. Not yet integrated into exec_job_list_ipython.loop_step()
parent b1d3e830
......@@ -268,6 +268,150 @@ class IPyResult(object):
self.update()
return True
class Oracle(object):
"""Selects data to be calculated in an adaptive evaluation.\
Parameters
----------
a : instance of `A`
Adaptive discriptor of the evaluation.
"""
def __init__(self, a):
# internal variables:
self._intervals = self._split_interval(a.interval, [None, None],
a.init_points)
self._requested_x = []
self._a = a
self._n_done = 0
self._sq_scales = None
self._min_vec = None
self._max_vec = None
self._refresh_min_max = 0
# internal functions:
def _sq_norm(self, origin, end, sq_scales):
return sum((i - j) ** 2 / k for i, j, k in itertools.izip(origin, end,
sq_scales))
def _max_min(self, points):
point_ar = np.array(points)
max_vec, min_vec = np.apply_along_axis(np.max, 0, point_ar), \
np.apply_along_axis(np.min, 0, point_ar)
return max_vec, min_vec
def _get_sq_scales(self):
# sq_scale need not be refreshed every time
self._refresh_min_max -=1
if self._refresh_min_max < 0:
y_data = [v[0] for v in self._intervals.itervalues()
if v[0] is not None]
if self._max_vec is not None:
y_data += [self._max_vec, self._min_vec]
self._max_vec, self._min_vec = self._max_min(y_data)
self._sq_scales = [max(i - j, 1e-4 * i, 1e-8) \
for i, j in itertools.izip(self._max_vec, self._min_vec)]
self._refresh_min_max = 10
return self._sq_scales
def _split_interval(self, interval, value, n_points=1):
points = np.linspace(interval[0], interval[1], n_points + 2)
values = [value[0]] + [None for point in points[1: -1]] + [value[1]]
return dict(((points[i], points[i + 1]), [values[i], values[i + 1]])
for i in xrange(len(points) - 1))
# functions visible from the outside:
def add_data(self, data):
"""Adds data to the internal intervals.
Parameters:
-----------
data : list of tuples (float, list or array of floats)
[(x0, [y00, y01, ...]), (x1, [y10, y11, ..] ), ...]
where (xi, [yij]) are data tuples x, y-array.
"""
a = self._a
# delete x values from list of requested x
for x, y in data:
self._requested_x.remove(x)
# determine new intervals
new_intervals ={}
finished_intervals = []
if self._n_done < max(a.init_points *.75, 7):
# We're in the beginning -> split all finished
for k, v in self._intervals.iteritems():
for x, y in data:
# find and set x, y in internal intervals
index = None
if k[0] == x:
index = 0
elif k[1] == x:
index = 1
if index is not None:
v[index] = y
self._n_done +=1
if v[(index+1)%2] is not None:
# interval is finished -> split it
new_intervals.update(
self._split_interval(k, v, a.n_split))
finished_intervals.append(k)
for k in finished_intervals:
del self._intervals[k]
self._intervals.update(new_intervals)
return
# Main loop, split only if not meeting precision goal
for k, v in self._intervals.iteritems():
for x, y in data:
# find and set x, y in internal intervals
index = None
if k[0] == x:
index = 0
elif k[1] == x:
index = 1
if index is not None:
v[index] = y
sq_scales = self._get_sq_scales()
if v[(index+1)%2] is not None:
# interval is finished -> split if precision is not met
dx = (k[0] - k[1]) ** 2 / a.sq_x_scale
dist = dx + self._sq_norm(v[0], v[1], sq_scales)
if dist > a.precision_goal_sq \
and dx > a.min_sq_x_scale:
new_intervals.update(
self._split_interval(k, v, a.n_split))
finished_intervals.append(k)
for k in finished_intervals:
del self._intervals[k]
self._intervals.update(new_intervals)
def request_points(self, n):
"""Returns points to be calculated.
Parameters:
-----------
n : int
Number of requested points
Returns:
--------
points : list of floats
Unique list of requested points of length n (or smaller if less
points are needed or available before additional data is added).
"""
points = []
for k, v in self._intervals.iteritems():
if (v[0] is None) and (not k[0] in self._requested_x):
points.append(k[0])
self._requested_x.append(k[0])
if len(points) == n:
return points
if (v[1] is None) and (not k[1] in self._requested_x):
points.append(k[1])
self._requested_x.append(k[1])
if len(points) == n:
return points
return points
def exec_job_list_ipython(ipycluster, module, jobs):
"""Execute a series of calculations using an ipython cluster client.
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment