def _compute_responses(rec_set1, rec_set2, *, metric=dist_rec_bounds): best_responses = defaultdict(lambda: Interval(float('inf'), float('inf'))) for r1, r2 in product(rec_set1, rec_set2): d, d_response = metric(r1, r2), best_responses[r1] best_responses[r1] = Interval(min(d.bot, d_response.bot), min(d.top, d_response.top)) return best_responses
def discretized_and_pointwise_hausdorff(recset1, recset2, k=3): xs = list(fn.mapcat(lambda r: r.discretize(k), recset1)) ys = list(fn.mapcat(lambda r: r.discretize(k), recset2)) error1 = max(r.error + r.shortest_edge for r in recset1) error2 = max(r.error + r.shortest_edge for r in recset2) error = error1 + error2 d12 = pointwise_hausdorff(xs, ys) return Interval(max(d12 - error, 0), d12 + error)
def directed_hausdorff(recs1, recs2, *, metric=dist_rec_bounds): responses = _compute_responses(recs1, recs2) values = bind(responses).Values() d = Interval(max(values[0].collect()), max(values[1].collect())) # TODO: can this be tightened? potential_moves = {r for r in recs1 if responses[r] & d} def is_required(r2): return any(responses[r1] & metric(r1, r2) for r1 in potential_moves) required_responses = {r2 for r2 in recs2 if is_required(r2)} return d, (potential_moves, required_responses)
def oracle_hausdorff_bounds2(recset1, recset2, f1, f2, eps=1e-1, k=3): refiner1 = edge_length_guided_refinement(recset1, f1) refiner2 = edge_length_guided_refinement(recset2, f2) while True: xs = list(fn.mapcat(lambda r: r.discretize(k), recset1)) ys = list(fn.mapcat(lambda r: r.discretize(k), recset2)) error1 = max(r.error + shortest_edge(r) for r in recset1) error2 = max(r.error + shortest_edge(r) for r in recset2) error = error1 + error2 d12 = pointwise_hausdorff(xs, ys) yield Interval(max(d12 - error, 0), d12 + error) recset1 = fn.first(filter(lambda xs: -xs[0][0] <= eps, refiner1)) recset2 = fn.first(filter(lambda xs: -xs[0][0] <= eps, refiner2)) recset1, recset2 = [r for _, r in recset1], [r for _, r in recset2] eps /= 2
def _midpoint(i): mid = i.bot + (i.top - i.bot) / 2 return Interval(mid, mid)
def dist_rec_bounds(r1, r2): return Interval(dist_rec_lowerbound(r1, r2), dist_rec_upperbound(r1, r2))