[Snippets/interpolatable] Use Hungarian algorithm from munkres or scipy when available
Fixes https://github.com/fonttools/fonttools/issues/815
This commit is contained in:
parent
a141ddc400
commit
179b8b5794
@ -77,36 +77,36 @@ def _matching_cost(G, matching):
|
|||||||
|
|
||||||
def min_cost_perfect_bipartite_matching(G):
|
def min_cost_perfect_bipartite_matching(G):
|
||||||
n = len(G)
|
n = len(G)
|
||||||
if n <= 8:
|
try:
|
||||||
# brute-force
|
from scipy.optimize import linear_sum_assignment
|
||||||
permutations = itertools.permutations(range(n))
|
rows, cols = linear_sum_assignment(G)
|
||||||
best = list(next(permutations))
|
# This branch untested
|
||||||
best_cost = _matching_cost(G, best)
|
assert rows == list(range(n))
|
||||||
for p in permutations:
|
return cols, _matching_cost(G, cols)
|
||||||
cost = _matching_cost(G, p)
|
except ImportError:
|
||||||
if cost < best_cost:
|
pass
|
||||||
best, best_cost = list(p), cost
|
|
||||||
return best, best_cost
|
|
||||||
else:
|
|
||||||
|
|
||||||
# Set up current matching and inverse
|
try:
|
||||||
matching = list(range(n)) # identity matching
|
from munkres import Munkres
|
||||||
matching_cost = _matching_cost(G, matching)
|
cols = [None] * n
|
||||||
reverse = list(matching)
|
for row,col in Munkres().compute(G):
|
||||||
|
cols[row] = col
|
||||||
|
return cols, _matching_cost(G, cols)
|
||||||
|
except ImportError:
|
||||||
|
pass
|
||||||
|
|
||||||
return matching, matching_cost
|
if n > 6:
|
||||||
# TODO implement real matching here
|
raise Exception("Install Python module 'munkres' or 'scipy >= 0.17.0'")
|
||||||
|
|
||||||
# Set up cover
|
# Otherwise just brute-force
|
||||||
cover0 = [max(c for c in row) for row in G]
|
permutations = itertools.permutations(range(n))
|
||||||
cover1 = [0] * n
|
best = list(next(permutations))
|
||||||
cover_weight = sum(cover0)
|
best_cost = _matching_cost(G, best)
|
||||||
|
for p in permutations:
|
||||||
while cover_weight < matching_cost:
|
cost = _matching_cost(G, p)
|
||||||
break
|
if cost < best_cost:
|
||||||
NotImplemented
|
best, best_cost = list(p), cost
|
||||||
|
return best, best_cost
|
||||||
return matching, matching_cost
|
|
||||||
|
|
||||||
|
|
||||||
def test(glyphsets, glyphs=None, names=None):
|
def test(glyphsets, glyphs=None, names=None):
|
||||||
|
Loading…
x
Reference in New Issue
Block a user