gpt4 book ai didi

c++ - Boost.Graph - algo.is_optimal() 断言

转载 作者:行者123 更新时间:2023-11-28 05:38:48 25 4
gpt4 key购买 nike

我正在尝试实现一个检测 arbitrage trading 的程序使用最小成本流算法的机会。此算法在 Boost.Graph 中以 boost::push_relabel_max_flow() 的形式实现,然后调用 boost::cycle_canceling()

以下是我已有的代码,省略了 boost::cycle_canceling 部分,因为我的程序在到达函数之前就死了。

    #include <boost/graph/adjacency_list.hpp>
#include <boost/property_map/property_map.hpp>
#include <boost/graph/push_relabel_max_flow.hpp>
#include <boost/graph/cycle_canceling.hpp>
#include <boost/graph/directed_graph.hpp>
#include <boost/config.hpp>
#include <iostream>
#include <string>



typedef boost::adjacency_list_traits<boost::vecS, boost::vecS, boost::directedS> Traits;

struct st_order {
double price;
double amount;
std::string type;
};

struct VertexProps {
unsigned int id;
};

struct EdgeProps {
double capacity;
double residual_capacity;
double weight;
Traits::edge_descriptor reverse;
};

typedef boost::adjacency_list<boost::vecS, boost::vecS, boost::directedS, VertexProps, EdgeProps > DirectedGraph;

int main() {


DirectedGraph g;

// ETH / BTC
std::vector<st_order> trades{
st_order{0.0101,10.0,"SELL"},
st_order{0.01,3.0,"BUY"},
st_order{0.0102,5.0,"SELL"},
st_order{0.2,42.0,"BUY"},
};


std::vector<boost::graph_traits<DirectedGraph>::vertex_descriptor> vertices;
for(unsigned int vertex_index = 0; vertex_index < trades.size(); vertex_index++)
{
vertices.push_back(boost::add_vertex({vertex_index}, g));
}


std::map<DirectedGraph::vertex_descriptor, std::map<DirectedGraph::vertex_descriptor, Traits::edge_descriptor>> edges;


int ifirst = 0;
for(auto& first : vertices)
{
int isecond = 0;
for(auto& second : vertices)
{

if(first == second || trades[ifirst].type.compare(trades[isecond].type) == 0)
{
isecond++;
continue;
}

double amount = trades[isecond].amount;

if(trades[isecond].type.compare("SELL") == 0)
amount = amount * trades[isecond].price;

edges[first][second] = boost::add_edge(first, second, {amount, amount, (trades[isecond].price / trades[ifirst].price)} , g).first;
std::cout << "Add Edge: From " << first << " to " << second << std::endl;

isecond++;
}
ifirst++;
}


for(auto& i : vertices)
{
for(auto& j : vertices)
{
if(i == j)
continue;

if(edges.find(i) != edges.end() && edges[i].find(j) != edges[i].end())
{
if(edges.find(j) == edges.end() || edges[j].find(i) == edges[j].end())
{
throw std::runtime_error("No return edge found: "+std::to_string(i)+" "+std::to_string(j));
}

auto edge = boost::edge(i,j,g).first;
g[edge].reverse = edges[i][j];

}
}
}



double flow = boost::push_relabel_max_flow(g, vertices[0], vertices[1],
boost::get(&EdgeProps::capacity, g),
boost::get(&EdgeProps::residual_capacity, g),
boost::get(&EdgeProps::reverse, g),
boost::get(boost::vertex_index, g)
);

// Now boost::cycle_canceling() would follow

std::cout << "END << std::endl;
return 0;
};

我程序的“正常”输出是:

Add Edge: From 0 to 1
Add Edge: From 0 to 3
Add Edge: From 1 to 0
Add Edge: From 1 to 2
Add Edge: From 2 to 1
Add Edge: From 2 to 3
Add Edge: From 3 to 0
Add Edge: From 3 to 2

如流程图:

enter image description here

我的程序在 push_relabel_max_flow 函数中断言。以下是完整的错误代码(在运行时打印):

    /usr/local/include/boost/graph/push_relabel_max_flow.hpp:707: typename
boost::property_traits<IndexMap>::value_type
boost::push_relabel_max_flow(Graph&, typename
boost::graph_traits<Graph>::vertex_descriptor, typename
boost::graph_traits<Graph>::vertex_descriptor, CapacityEdgeMap,
ResidualCapacityEdgeMap, ReverseEdgeMap, VertexIndexMap) [with Graph =
boost::adjacency_list<boost::vecS, boost::vecS, boost::directedS,
VertexProps, EdgeProps>; CapacityEdgeMap =
boost::adj_list_edge_property_map<boost::directed_tag, double, double&, long
unsigned int, EdgeProps, double EdgeProps::*>; ResidualCapacityEdgeMap =
boost::adj_list_edge_property_map<boost::directed_tag, double, double&, long
unsigned int, EdgeProps, double EdgeProps::*>; ReverseEdgeMap =
boost::adj_list_edge_property_map<boost::directed_tag,
boost::detail::edge_desc_impl<boost::directed_tag, long unsigned int>,
boost::detail::edge_desc_impl<boost::directed_tag, long unsigned int>&, long
unsigned int, EdgeProps, boost::detail::edge_desc_impl<boost::directed_tag,
long unsigned int> EdgeProps::*>; VertexIndexMap =
boost::vec_adj_list_vertex_id_map<VertexProps, long unsigned int>; typename
boost::property_traits<IndexMap>::value_type = double; typename
boost::graph_traits<Graph>::vertex_descriptor = long unsigned int]: Assertion
`algo.is_optimal()' failed.

在消息的最后您可以看到Assertion: algo.is_optimal() failed。我完全不知道这意味着什么。

在源文件 (boost/graph/push_relabel_max_flow.hpp) 中定义为:

bool is_optimal() {
// check if mincut is saturated...
global_distance_update();
return get(distance, src) >= n;
}

我用谷歌搜索了一下,没有找到任何东西。我是否以错误的方式传递了参数?是不是因为我使用 double 作为容量(尽管,如果我没记错的话,“documentation ”描述了可以使用 double 作为容量)?另外,我在 documentation 中发现了这句话:

The CapacityEdgeMap argument cap must map each edge in E to a positive number, and each edge in E^T to 0.

加粗部分是什么意思?这是否意味着我必须将所有从汇点到顶点的出边的容量设置为 0?

最佳答案

您需要将反向边缘的容量设置为 0。

所以你需要:

auto edge = boost::edge(i,j,g).first;
g[edge].reverse = edges[i][j];
g[edges[i][j]].capacity = 0;

我不确定为什么会这样。调查read_dimacs.hpp我注意到他们创建了他们的反向边缘并给他们 0 容量。页面下方的大约 3/4:

capacity[e1] = cap;
capacity[e2] = 0;
reverse_edge[e1] = e2;
reverse_edge[e2] = e1;

可能没有此约束,算法将尝试将这些视为正常边缘。您引用的文档部分对此进行了描述,但并不十分明显。

There are several special requirements on the input graph and property map parameters for this algorithm. First, the directed graph G=(V,E) that represents the network must be augmented to include the reverse edge for every edge in E. That is, the input graph should be Gin = (V,{E U E^T}). The ReverseEdgeMap argument rev must map each edge in the original graph to its reverse edge, that is (u,v) -> (v,u) for all (u,v) in E. The CapacityEdgeMap argument cap must map each edge in E to a positive number, and each edge in E^T to 0.

我认为这里的 E^T 意味着转置,而不是目标。你要知道有向邻接矩阵的转置其实就是所有边的逆。这就是为什么他们说输入图是 G = {V, E U E^T}。边缘加上需要添加的反向边缘。

旁注:在 push-relable example 中将 long 更改为 double工作得很好。

关于c++ - Boost.Graph - algo.is_optimal() 断言,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37624480/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com