构建无限期的MDP,通过必须访问状态实现成本最小化

时间:2016-10-17 03:00:57

标签: java python algorithm

寻找一些帮助来解决无限期的问题,成本最小化,有些人必须访问各州。

我们获得预算b和成本矩阵M,它代表州之间旅行的扣除(Mij代表从i到j旅行的成本),类似于经典的旅行商问题。在这种情况下,时间可能是负的,表示预算的增加,Mij可能不一定等于Mji。同样在这种情况下M是4x4,但情况可能并非如此,通常可以说3< = len(M)< = 5,因为我认为这可能需要一些具有大量操作的强力方法......

0 1 -3 1
6 0 2 2
4 2 0 3
1 2 3 0

每一行代表给定的状态i,然后每列代表向j行进的成本。

问题在于:给定b和M,排除state = 0和state = len(M)我们可以前往并以state = len(M)结束的唯一状态的最大数量是多少,其中b> = 0.

鉴于上面的M,并且b = 0,那么我认为输出将是[2],路径是[0] - > [2] - > [3]并且完整的推出看起来像这样:

state nextstate deduction time
 --       0        ---     0
 0        2         -3     3
 2        3         3      0

我试图通过电子贪婪的解决方案和启发式策略来解决这个问题作为强化学习问题来选择下一个状态,我也认为这就像一个TSP并使用Floyd-Warshall查看解决方案但是我不太确定如何在问题设置中适应约束。

我认为有一种方法可以找到直接的解决方案,我的直觉似乎能够查看一般的M和给定的b并提出解决方案,但我无法干净地说出算法...

对于如何干净利落地提出并提出直接解决方案,我们对此表示赞赏。

1 个答案:

答案 0 :(得分:1)

如果您的成本矩阵包含负循环,则最终可以访问所有状态。您可以使用Bellman-Ford来检测周期,因此答案的其余部分假定不存在此类周期。

该算法由三部分组成。首先,它找到所有路径的成本低于从开始状态到结束状态的预算。对于每个这样的路径,访问的状态和总成本被跟踪。然后它找到源自(并终止于)结束状态的所有循环并跟踪访问状态&总费用。

在知道所有路径和循环之后,算法开始向路径添加循环。如果循环添加新状态并且总成本在预算内,则添加成功。继续添加,直到无法向现有路径添加循环。最后,选择包含最多访问状态的路径。

这是上面的非精炼实现:

M = [
    [0, 2, 2, 2, -1],
    [6, 0, 2, 2, -1],
    [6, 3, 0, 2, -1],
    [6, 3, 2, 0, -1],
    [6, 3, 2, 2, 0]
]

BUDGET = 1
SOURCE = 0
DEST = len(M) - 1

def all_paths_step(source, dest, visited, cost):
    for i in range(len(M)):
        if i in visited:
            continue
        new_cost = cost + M[source][i]
        new_set = visited | {i}
        if i == dest:
            yield new_set, new_cost
        elif i not in visited:
            yield from all_paths_step(i, dest, new_set, new_cost)

def all_paths(source, dest, cost=0):
    result = {}
    for states, cost in all_paths_step(source, dest, frozenset([source]), cost):
        result[states] = min(result.get(states, float('inf')), cost)

    return result

to_dest = all_paths(SOURCE, DEST)
loops = {}

for i in range(len(M)):
    if i == DEST:
        continue
    for states, cost in all_paths(i, len(M) - 1, M[len(M) - 1][i]).items():
        loops[states] = min(loops.get(states, float('inf')), cost)

possible = {visited: cost for visited, cost in to_dest.items() if cost <= BUDGET}

process = set(possible.keys())
while process:
    process_next = set()
    while process:
        states = process.pop()
        for path, cost in loops.items():
            cost += possible[states]
            new_states = states | path
            if path <= states or cost >= possible.get(new_states, BUDGET + 1):
                continue
            possible[new_states] = cost
            process_next.add(new_states)
    process = process_next

print('result: {}'.format(max(possible, key=len)) if possible else 'none')

输出,访问状态无特定顺序:

result: frozenset({0, 2, 3, 4})