在 c++ 中通过网格/矩阵找到成本优化的路径
我遇到了一个问题,在网上找不到太多帮助。我需要从多个数字向量中找到最小成本的数字组合。所有向量的向量大小都相同。 例如,考虑以下情况:
row [0]: a b c d
row [1]: e f g h
row [2]: i j k l
现在我需要通过从每一行即向量中取出一个元素来找到数字组合,例如:aei
之后,我需要找到其他三个不相交的组合,例如:bfj、cgk、dhl。我根据选择的这四种组合来计算成本。目标是找到成本最低的组合。另一种可能的组合可以是:afj、bei、chk、dgl。如果总列数为 d,总行数为 k,则可能的总组合为 d^k。行存储为向量。我被困在这里,我发现很难为上述过程编写算法。如果有人可以提供帮助,我将非常感激。
谢谢。
// I am still working on the algorithm. I just have the vectors and the cost function.
//Cost Function , it also depends on the path chosen
float cost(int a, int b, PATH to_a) {
float costValue;
...
...
return costValue;
}
vector< vector < int > > row;
//populate row
...
...
//Suppose
// row [0]: a b c d
// row [1]: e f g h
// row [2]: i j k l
// If a is chosen from row[0] and e is chosen from row[1] then,
float subCost1 = cost(a,e, path_to_a);
// If i is chosen from row[2] ,
float subCost2 = cost(e,i,path_to_e);
// Cost for selecting aei combination is
float cost1 = subCost1 + subCost2;
//similarly other three costs need to be calculated by selecting other remaining elements
//The elements should not intersect with each other eg. combinations aei and bej cannot exist on the same set.
//Suppose the other combinations chosen are bfj with cost cost2, cgk with cost cost3 and dhl with cost cost4
float totalCost = cost1 + cost2 + cost3 + cost4;
//This is the cost got from one combination. All the other possible combinations should be enumerated to get the minimum cost combination.
I am stuck with a problem and could not find much help online. I need to find the minimum cost combination of numbers from multiple vectors of numbers. The vector size is same for all vectors.
For example, consider the following :
row [0]: a b c d
row [1]: e f g h
row [2]: i j k l
Now I need to find the combination of numbers by taking one element from each row i.e vector, eg: aei
After this, i need to find other three combinations that do not intersect with one another, eg: bfj, cgk, dhl. I calculate the cost based on these four combination chosen. The goal is to find the combination that gives the minimum cost. Another possible combination can be: afj, bei, chk, dgl. If the total number of columns is d and rows is k, the total combination possible is d^k. The rows are stored as vectors. I am stuck here, I am finding it hard to write an algorithm for the above process. I would really appreciate if somebody could help.
Thanks.
// I am still working on the algorithm. I just have the vectors and the cost function.
//Cost Function , it also depends on the path chosen
float cost(int a, int b, PATH to_a) {
float costValue;
...
...
return costValue;
}
vector< vector < int > > row;
//populate row
...
...
//Suppose
// row [0]: a b c d
// row [1]: e f g h
// row [2]: i j k l
// If a is chosen from row[0] and e is chosen from row[1] then,
float subCost1 = cost(a,e, path_to_a);
// If i is chosen from row[2] ,
float subCost2 = cost(e,i,path_to_e);
// Cost for selecting aei combination is
float cost1 = subCost1 + subCost2;
//similarly other three costs need to be calculated by selecting other remaining elements
//The elements should not intersect with each other eg. combinations aei and bej cannot exist on the same set.
//Suppose the other combinations chosen are bfj with cost cost2, cgk with cost cost3 and dhl with cost cost4
float totalCost = cost1 + cost2 + cost3 + cost4;
//This is the cost got from one combination. All the other possible combinations should be enumerated to get the minimum cost combination.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
这是我们到目前为止所得到的:
从描述中我收集到的建议是您有一个像
额外的约束是后续节点必须从下一个等级中获取(ad、eh、il 是三个等级;一旦访问了最后一个rank中的节点,该路径必须从第一个rank
中的任何未访问节点继续。
边是加权的,因为它们具有关联的成本。但是,权重函数对于图算法来说不是传统的,因为成本取决于。完整的路径,而不仅仅是每个路径的终点边。
鉴于此,我相信我们正处于“Full Cover”问题的领域(需要 A* 算法,最著名的是 Knuths Dancing Links 论文)。
具体如果没有进一步的信息(路径的等价性、成本函数的特定属性),获得满足约束的“最便宜”哈密尔顿路径的最著名算法将是生成
这就是为什么我开始并编写一个非常愚蠢的强力生成器,它生成 NxM 通用网格中可能的所有唯一路径。
3×4 样本网格的宇宙尽头
输出为 4!3 = 13824 条可能的路径...推断为 6×48 列,得到 6!48 = 1.4×10137 种可能性。很明显如果不进一步优化,问题将难以解决(NP Hard 之类的东西——我从来不记得那些微妙的定义)。
运行时间的爆炸性增长是震耳欲聋的:
在 48x6 下,我们会看到...什么...8.3x10107 年 (仔细阅读)
实时查看: http://ideone.com/YsVRE
无论如何,这是 python代码(全部预设为2×3网格)
Here is what we got up till now:
From the description I glean the suggestion that you have a basic graph like
a path has to be constructed that visits all nodes in the grid (Hamiltonian cycle).
The extra constraint is that subsequent nodes have to be taken from the next rank (a-d, e-h, i-l being the three ranks; once a node from the last rank was visited, the path has to continue with any unvisited node from the first rank
The edges are weighted, in that they have a cost associated. However, the weight function is not traditional for graph algorithms in that the cost depends on the full path, not just the end-points of each edge.
In the light of this I believe we are in the realm of 'Full Cover' problems (requiring A* algorithm, most famous from Knuths Dancing Links paper).
Specifically Without further information (equivalence of paths, specific properties of the cost function) the best known algorithm to get the 'cheapest' hamiltonian path that satisfies the constraints will be to
Which is why I have set off and wrote a really dumb brute force generator that generates all the unique paths possible in a generic grid of NxM.
The End Of The Universe
Output for the 3×4 sample grid is 4!3 = 13824 possible paths... Extrapolating that to 6×48 columns, leads to 6!48 = 1.4×10137 possibilities. It is very clear that without further optimization the problem is untractible (NP Hard or something -- I never remember quite the subtle definitions).
The explosion of runtime is deafening:
At 48x6 we would be looking at... what... 8.3x10107 years (read that closely)
See it live: http://ideone.com/YsVRE
Anyways, here is the python code (all preset for 2×3 grid)
首先,一个观察结果有一点帮助。
我认为 4!^3 结果没有反映出 { aei, bfj, cgk, dhl } 和(例如){ bfj, aei, cgk, dhl } 具有相同成本的事实。
这意味着我们只需要考虑以下形式的序列。
这种等价将不同情况的数量减少了 4!
另一方面,@sehe 有 3x4 给出 4!^3 (我同意),所以类似的 6x48 需要 48!^6。其中“只有”48!^5 是不同的。现在是 2.95 × 10^305。
使用 3x4 示例,这是给出某种答案的算法的开始。
请注意,这不是完全详尽的搜索。
我还从中看到,这仍然是大量的计算。第一遍仍然需要计算 48^6 (12,230, 590, 464) 成本。我想这是可以做到的,但需要付出很多努力。相比之下,后续的通行证会便宜一些。
First, one observation that helps very slightly.
I think the 4!^3 result does not capture the fact that { aei, bfj, cgk, dhl } and (for example) { bfj, aei, cgk, dhl } have the same cost.
What this means is that we only need to consider sequences of the form
This equivalence cuts the number of distinct cases by 4!
On the other hand, @sehe has 3x4 gives 4!^3 (I agree), so similarly 6x48 requires 48!^6. Of these “only” 48!^5 are distinct. This is now 2.95 × 10^305.
Using the 3x4 example, here is a start on an algorithm which gives some sort of answer.
Note that is not a full exhaustive search.
I also see from this is that this is still a lot of computation. That first pass still requires 48^6 (12,230, 590, 464) costs to be computed. I guess that can be done, but will take a lot of effort. The subsequent passes will be cheap in comparison.
编辑:添加了完整的解决方案
正如其他答案已经指出的那样,你的问题太难了,无法用暴力来面对。这类问题的出发点始终是模拟退火。我创建了一个实现该算法的小应用程序。
查看问题的另一种方法是最小化复杂函数。此外,您对可能的解决方案还有额外的限制。我从随机有效配置(满足您的约束)开始,然后修改每次更改一个元素的随机解决方案。我强制应用程序仅执行有效的转换。代码非常清楚。
我创建了一个模板函数,因此您只需提供必要的函数对象和结构。
当然,您不能保证该解决方案是最好的(这是一种启发式方法)。然而,这是一个很好的起点。
您没有提供完整的功能成本,因此我实现了自己的功能成本,以便我可以简单地检查最终结果。您只需提供功能成本即可完成工作。
你可能会让程序更加高效,有很大的改进空间,但是逻辑已经存在,你可以很容易地实现你的功能。
复杂度
算法的复杂度为 E*I*C,其中
I = 迭代次数
C = 随机配置的数量(以避免局部最小值)
E = 能量函数(或函数成本)的计算
在这种情况下,E 实际上是 N*M,其中 N 和 M 是初始矩阵的维度。
如果您对模拟退火结果不满意,可以尝试遗传算法。
EDIT: ADDED A COMPLETE SOLUTION
As the other answers have already pointed out you problem is too difficult to be face with brute force. The starting point of this kind of problem is always Simulated annealing. I have create a small application that implement the algorithm.
Another way to see your problem is to minimize a complex function. Also you have an extra constraint on the possible solution. I start with a random valid configuration (that meet your constraints), then I modified that random solution changing an element per time. I force the application to perform just valid transition. The code is pretty clear.
I have created a template function, so you need just to provide the necessary function objects and structure.
Of course you have no guarantee that the solution is the best one (it is an heuristic method). However it is a good starting point.
You haven't provide a complete function cost, so I have implement my own one that allows me to simply check the final result. You need just to provide the function cost and the job is done.
You will probably make the program more efficient, there is plenty of room for improvement, but the logic is there and you can implement your function easily enough.
Complexity
The complexity of the algorithm is E*I*C where
I = number of iterations
C = number of random configuration (to avoid local minimum)
E = calculation of energy function (or function cost)
In this case E is actually N*M where N and M are the dimensions of the initial matrix.
If you are not happy with the Simulated annealing result you may try genetic algorithms.
您可以递归地解决该问题。
该方法的输入是要计算的第一个向量的索引,并且该向量在函数外部共享。
对于剩余两行的情况,可以使用回溯来计算解决方案。在这种情况下,您只需找到更便宜的配对即可。
对于超过两行的情况,您应该使用下一个索引调用该方法,获取部分结果,然后再次使用回溯计算最小值。
当流程回到第一个向量时,您可以将结果合并为最终结果。
You can solve the problem recursively.
The input to the method is the index of the first vector to compute, and the vector is shared outside the function.
For the case there are two rows remaining, solution can be computed using backtracking. In this case, you only need to find the pair-isation less expensive.
For the case there are more than two rows, you should call the method with the next index, get the partial result, and then compute the minimum value using backtracking again.
When the flow get back to the first vector, you can consolidate the result as the final result.
值得注意的是,对于一些有趣的路径成本选择,有一个多时间算法,例如,如果路径成本是边成本之和,则可以通过对所有 i 运行匈牙利算法来找到最优解在第 i 行和第 i + 1 行。
It's worth noting that for some interesting choices of path cost, there's a poly-time algorithm, e.g., if the path cost is the sum of the edge costs, then the optimal solution can be found by running, for all i, the Hungarian algorithm on rows i and i + 1.