ILP图循环检测

ILP graph cycle detection

我完全被这个(整数)线性规划公式任务困住了:
输入:包含环的有向边加权图。
目标:找到一组边,它们的权重总和最小,这样如果从图中删除这些边,图就会变成非循环的。

编辑: 对于任何感兴趣的人,我发现(在我朋友的帮助下),您可以使用拓扑排序来解决这个问题。您只需要为每条边引入一个约束,这样:
topologicalOrder[ edge.parent ] << topologicalOrder[ edge.child ] + ( M * edgeInactive[edge])
其中 topologicalOrder[node] 是节点拓扑位置的整数数组,edgeInactive 是布尔数组,表示边在结果(非循环)图中是否处于活动状态。 M 是用于在 edgeActive[edge] == true.
时“关闭”约束的 Big M 方法 然后你只需要最小化非活动边缘的权重总和。

旧(较慢)解决方案:
我的想法是创建节点的拓扑排序(对于非循环图,在拓扑排序时,所有边将按从左到右的方向排列),但是当我得到带循环的图时,我将寻找总和的拓扑排序从右到左的边数最少。

这种方法可行,但速度很慢...

(我正在尝试用 Gurobi 解决这个问题,但我认为这几乎是一般的线性规划公式问题。) 我的代码:

# Variables
x = model.addVars(nodeCount, nodeCount, vtype=g.GRB.BINARY) # matrix of size nodeCount * nodeCount, where x[i,j] denotes if node i is topologically before node j

#Constraints
for e in edges:
    model.addConstr(x[e.child, e.parent] == 1 - x[e.parent, e.child])  # x[i,j] needs to be equal to negative value of x[j,i]

    for k in range(nodeCount):
        model.addConstr(  x[e.parent, e.child] + x[e.child, k] - x[e.parent, k] <= 1) # Without this constraint solver produced invalid ordering results so I came up with this equation. But I'm not sure if this is the best way to solve this issue..


# Objective
sumNegativeEdges = 0;
for e in edges:
    sumNegativeEdges+= (x[e.child, e.parent]) * e.weight; # Adding just weight of edges where child is topologically before the parent

model.setObjective(sumNegativeEdges, g.GRB.MINIMIZE) 

如有任何帮助,将不胜感激...

这看起来像是一个(一般的)NP 难问题:minimum feedback arc set. At least this answer 表明了这一点。

您可能会使用此关键字找到更多资源。

我记得当我在 Kemeny–Young method

上做一些 ILP 工作时,我读过关于 以上 问题的 ILP 公式

在 Google 上快速查找它,学者将我们带到:

Ali, Alnur, and Marina Meilă. "Experiments with Kemeny ranking: What works when?." Mathematical Social Sciences 64.1 (2012): 28-40.

其中说:

"The above ILP formulation has been given before [10, 28]. This formulation can also be interpreted as solving the minimum weighted feedback arc set problem from computer science [10, 19]"

我猜你可能会从这篇论文开始 (Link to pdf as referenced by Google Scholar)

我发现(在我朋友的帮助下),你可以使用拓扑排序来解决这个问题。您只需要为每条边引入一个约束,这样:
topologicalOrder[ edge.parent ] << topologicalOrder[ edge.child ] + ( M * edgeInactive[edge])
其中 topologicalOrder[node] 是节点拓扑位置的整数数组,edgeInactive 是布尔数组,表示边在结果(非循环)图中是否处于活动状态。 M 是用于在 edgeActive[edge] == true.
时“关闭”约束的 Big M 方法 然后你只需要最小化非活动边缘的权重总和。