Number of ways to go through a partially ordered set

时光毁灭记忆、已成空白 提交于 2019-12-23 18:00:44

问题


This is built upon a previous question Solve a simple packing combination with dependencies, although there is no need to check out that question to understand this one.

This question asks about the fastest ways to count the number of linear extensions of a partially ordered set.

Such an partially ordered list can be visualized as the feasibility of a packing configuration, given arbitrary ordering of the objects. The question is than equivalent to what are the possible ordering of all the blocks handed to you for you to achieve the shown packing configuration, if the blocks cannot be moved once placed?

In this example, all blocks ABCDEFG need to be laid down,dependencies for A,B,C,D: set{}, E: set{A,B},F: set{B,C} G: set{C,D}.

You can get all possibilities of completing the partially ordered set by checking all permutations of 7 blocks and count the number that meets the dependencies. A faster alternative is provided by גלעד ברקן in the previous post who used a graph structure that terminate further search into a branch if the dependencies are not met in nodes already explored.

nodes = {
  'A': {
    'neighbours': ['B','C','D','E','F','G'], 'dependency': set()},
  'B': {
    'neighbours': ['A','C','D','E','F','G'], 'dependency': set()},
  'C': {
    'neighbours': ['A','B','D','E','F','G'], 'dependency': set()},
  'D': {
    'neighbours': ['A','B','C','E','F','G'], 'dependency': set()},
  'E': {
    'neighbours': ['C','D','F','G'], 'dependency': set(['A','B'])},
  'F': {
    'neighbours': ['A','D','E','G'], 'dependency': set(['B','C'])},
  'G': {
    'neighbours': ['A','D','E','G'], 'dependency': set(['C','D'])},

}

def f(key, visited):
  if len(visited) + 1 == len(nodes):
    return 1

  if nodes[key]['dependency'] and not nodes[key]['dependency'].issubset(visited):
    return 0

  result = 0

  for neighbour in nodes[key]['neighbours']:
    if neighbour not in visited:
      _visited = visited.copy()
      _visited.add(key)
      result += f(neighbour, _visited)

  return result

print 2 * f('A', set()) + 2 * f('B', set()) # exploiting symmetry

My question is that if there is any way to further optimize upon גלעד ברקן's algorithm without losing generality? I can probably make it faster if the dependencies are scarce and the list can be further broken down into independent sub-lists but that's not the case for this particular example.

来源:https://stackoverflow.com/questions/50126232/number-of-ways-to-go-through-a-partially-ordered-set

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!