[varLib] Speed up IUP DP when forced set is empty
Drives it into acceptable speed now. Note that I'm getting better gvar size after this patch, which I didn't expect. So, either this algorithm or the previous one was buggy. :(
This commit is contained in:
parent
7fa1ce1ca7
commit
91e4220193
@ -279,17 +279,7 @@ def _iup_contour_optimize_dp(delta, coords, forced={}, tolerance=0):
|
|||||||
if j in forced:
|
if j in forced:
|
||||||
break
|
break
|
||||||
|
|
||||||
# Assemble solution.
|
return chain, costs
|
||||||
solution = set()
|
|
||||||
i = n - 1
|
|
||||||
while i is not None:
|
|
||||||
solution.add(i)
|
|
||||||
i = chain[i]
|
|
||||||
assert forced <= solution, (forced, solution)
|
|
||||||
|
|
||||||
delta = [delta[i] if i in solution else None for i in range(n)]
|
|
||||||
|
|
||||||
return delta, costs[n - 1]
|
|
||||||
|
|
||||||
def _rot_list(l, k):
|
def _rot_list(l, k):
|
||||||
"""Rotate list by k items forward. Ie. item at position 0 will be
|
"""Rotate list by k items forward. Ie. item at position 0 will be
|
||||||
@ -304,19 +294,6 @@ def _rot_set(s, k, n):
|
|||||||
if not k: return s
|
if not k: return s
|
||||||
return {(v + k) % n for v in s}
|
return {(v + k) % n for v in s}
|
||||||
|
|
||||||
def _iup_contour_optimize_dp_with_offset(delta, coords, offset, forced, tolerance):
|
|
||||||
n = len(delta)
|
|
||||||
|
|
||||||
delta = _rot_list(delta, offset)
|
|
||||||
coords = _rot_list(coords, offset)
|
|
||||||
forced = _rot_set(forced, offset, n)
|
|
||||||
|
|
||||||
delta, cost = _iup_contour_optimize_dp(delta, coords, forced, tolerance)
|
|
||||||
|
|
||||||
delta = _rot_list(delta, -offset)
|
|
||||||
|
|
||||||
return delta, cost
|
|
||||||
|
|
||||||
def _iup_contour_optimize(delta, coords, tolerance=0.):
|
def _iup_contour_optimize(delta, coords, tolerance=0.):
|
||||||
n = len(delta)
|
n = len(delta)
|
||||||
|
|
||||||
@ -340,7 +317,7 @@ def _iup_contour_optimize(delta, coords, tolerance=0.):
|
|||||||
forced = _iup_contour_bound_forced_set(delta, coords, tolerance)
|
forced = _iup_contour_bound_forced_set(delta, coords, tolerance)
|
||||||
# The _iup_contour_optimize_dp() routine returns the optimal encoding
|
# The _iup_contour_optimize_dp() routine returns the optimal encoding
|
||||||
# solution given the constraint that the last point is always encoded.
|
# solution given the constraint that the last point is always encoded.
|
||||||
# To remove this constraint, we do two different things, depending on
|
# To remove this constraint, we use two different methods, depending on
|
||||||
# whether forced set is non-empty or not:
|
# whether forced set is non-empty or not:
|
||||||
|
|
||||||
if forced:
|
if forced:
|
||||||
@ -348,21 +325,42 @@ def _iup_contour_optimize(delta, coords, tolerance=0.):
|
|||||||
# such that the last point in the list is a forced point.
|
# such that the last point in the list is a forced point.
|
||||||
k = (n-1) - max(forced)
|
k = (n-1) - max(forced)
|
||||||
assert k >= 0
|
assert k >= 0
|
||||||
delta, _ = _iup_contour_optimize_dp_with_offset(delta, coords, k, forced, tolerance)
|
|
||||||
|
delta = _rot_list(delta, k)
|
||||||
|
coords = _rot_list(coords, k)
|
||||||
|
forced = _rot_set(forced, k, n)
|
||||||
|
|
||||||
|
chain, costs = _iup_contour_optimize_dp(delta, coords, forced, tolerance)
|
||||||
|
|
||||||
|
# Assemble solution.
|
||||||
|
solution = set()
|
||||||
|
i = n - 1
|
||||||
|
while i is not None:
|
||||||
|
solution.add(i)
|
||||||
|
i = chain[i]
|
||||||
|
assert forced <= solution, (forced, solution)
|
||||||
|
delta = [delta[i] if i in solution else None for i in range(n)]
|
||||||
|
|
||||||
|
delta = _rot_list(delta, -k)
|
||||||
else:
|
else:
|
||||||
# Brute-force: rotate and retry until all points on the contour are part
|
chain, costs = _iup_contour_optimize_dp(delta+delta, coords+coords, forced, tolerance)
|
||||||
# of at least one solution. The best of those solutions is the optimal
|
# TODO add lookback=n to DP
|
||||||
# solution.
|
best_sol, best_cost = None, n+1
|
||||||
best_delta, best_cost = None, n + 1
|
|
||||||
tocover = set(range(n))
|
for start in range(n-1, 2*n-1):
|
||||||
while tocover:
|
# Assemble solution.
|
||||||
k = (n-1) - max(tocover)
|
solution = set()
|
||||||
assert k >= 0
|
i = start
|
||||||
this_delta, this_cost = _iup_contour_optimize_dp_with_offset(delta, coords, k, forced, tolerance)
|
while i > start - n:
|
||||||
if this_cost < best_cost:
|
solution.add(i % n)
|
||||||
best_delta, best_cost = this_delta, this_cost
|
i = chain[i]
|
||||||
tocover -= {i for i,v in enumerate(this_delta) if v is not None}
|
if i == start - n:
|
||||||
delta = best_delta
|
cost = costs[start] - costs[start - n]
|
||||||
|
if cost <= best_cost:
|
||||||
|
best_sol, best_cost = solution, cost
|
||||||
|
|
||||||
|
delta = [delta[i] if i in best_sol else None for i in range(n)]
|
||||||
|
|
||||||
|
|
||||||
return delta
|
return delta
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user