Last active
January 31, 2018 06:21
-
-
Save william-silversmith/5d1668fffed7a71688932c44ee266414 to your computer and use it in GitHub Desktop.
Fully generalized COUNTLESS algorithm with a (relatively) memory efficient dynamic programming solution
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from itertools import combinations | |
from functools import reduce | |
import numpy as np | |
def countlessND(data, factor): | |
assert len(data.shape) == len(factor) | |
sections = [] | |
mode_of = reduce(lambda x,y: x * y, factor) | |
majority = int(math.ceil(float(mode_of) / 2)) | |
data += 1 # offset from zero | |
# This loop splits the 2D array apart into four arrays that are | |
# all the result of striding by 2 and offset by (0,0), (0,1), (1,0), | |
# and (1,1) representing the A, B, C, and D positions from Figure 1. | |
for offset in np.ndindex(factor): | |
part = data[tuple(np.s_[o::f] for o, f in zip(offset, factor))] | |
sections.append(part) | |
pick = lambda a,b: a * (a == b) | |
lor = lambda x,y: x + (x == 0) * y # logical or | |
subproblems = [ {}, {} ] | |
results2 = None | |
for x,y in combinations(range(len(sections) - 1), 2): | |
res = pick(sections[x], sections[y]) | |
subproblems[0][(x,y)] = res | |
if results2 is not None: | |
results2 = lor(results2, res) | |
else: | |
results2 = res | |
results = [ results2 ] | |
for r in range(3, majority+1): | |
r_results = None | |
for combo in combinations(range(len(sections)), r): | |
res = pick(subproblems[0][combo[:-1]], sections[combo[-1]]) | |
if combo[-1] != len(sections) - 1: | |
subproblems[1][combo] = res | |
if r_results is not None: | |
r_results = lor(r_results, res) | |
else: | |
r_results = res | |
results.append(r_results) | |
subproblems[0] = subproblems[1] | |
subproblems[1] = {} | |
results.reverse() | |
final_result = lor(reduce(lor, results), sections[-1]) - 1 | |
data -= 1 | |
return final_result |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment