四色定理指出,对于连通图,任何节点都可以着色,使得相邻节点不共享相同的颜色,并且对于任何图,都有一个需要不超过四种颜色的解决方案。
我在堆栈溢出上找到了满足四色定理的Python代码,并且我已合并该代码来处理地理空间数据,这样共享边界的两个多边形不会共享相同的颜色。我找到的四色定理代码返回一个 Python 生成器对象(我对生成器不熟悉),并将这个生成器对象转换为 Python 列表以进行进一步处理。这在我的几个多边形的测试数据上运行良好且快速。由于四色定理有不止一种解决方案,因此我筛选了可能的解决方案(从生成器创建的列表),并找到具有最均匀颜色分布的解决方案,以获得最好的制图效果。
现在代码可以运行了,我在美国 50 个多边形测试数据集上对其进行了测试。问题是,四色定理有太多的解决方案,导致要列出的生成器太大,以至于导致我的 IDE 崩溃。我假设我可以将可能的解决方案限制为几千个解决方案,并在那几千个解决方案中找到具有良好颜色分布的合适解决方案。
如何限制从生成器返回的列表项的数量?
下面是返回生成器的函数。这个函数的工作原理和生成器对象超出了我的技能水平。我确实知道如何限制函数中或转换为列表时的解决方案(或列表项)的数量。
def colour_map(nodes, edges, ncolours=4):
colours = range(ncolours)
#The edges that meet each node
node_edges = dict((n, set()) for n in nodes)
for e in edges:
n0, n1 = e
node_edges[n0].add(e)
node_edges[n1].add(e)
for n in nodes:
node_edges[n] = list(node_edges[n])
#Set to cover
coloured_edges = list(product(colours, edges))
X = nodes + coloured_edges
#Subsets to cover X with
Y = dict()
#Primary rows
for n in nodes:
ne = node_edges[n]
for c in colours:
Y[(n, c)] = [n] + [(c, e) for e in ne]
#Dummy rows
for i, ce in enumerate(coloured_edges):
Y[i] = [ce]
X = exact_cover(X, Y)
#Set first two nodes
partial = [(nodes[0], 0), (nodes[1], 1)]
for s in partial:
select(X, Y, s)
for s in solve(X, Y, []):
s = partial + [u for u in s if not isinstance(u, int)]
s.sort()
yield s
#call the color map function to get the generator object...
all_solutions = colour_map(nodes, adjacent_polygons_graph, ncolours=3)
#convert the generator object to a list
solution_list = list(all_solutions)
我尝试按照建议限制产量数量,但这会返回一个空的生成器。
yield_counter = 0
for s in solve(X, Y, []):
yield_counter +=1
s = partial + [u for u in s if not isinstance(u, int)]
s.sort()
yield s
if yield_counter == 100:
break
如果您想保留该方法来产生结果并将其留给调用者来确定他们何时“足够”,您可以这样做:
def foo():
while True:
yield "hi"
results = foo()
for _ in range(10):
print(next(results))
## or
results = foo()
print([next(results) for _ in range(10)])
也许是这样的:
all_solutions = colour_map(nodes, adjacent_polygons_graph, ncolours=3)
for _ in range(10):
solution = next(all_solutions)
## do something with this solution
或
all_solutions = colour_map(nodes, adjacent_polygons_graph, ncolours=3)
enough_solutions = [next(all_solutions) for _ in range(10)]
## do something with this first 10 solutions
请注意,这种模式可能需要您防范
StopIteration
,但只要您确定消耗的量少于可能产生的量,就应该没问题。