首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Boost.Graph - algo.is_optimal()断言

Boost.Graph - algo.is_optimal()断言
EN

Stack Overflow用户
提问于 2016-06-03 22:44:14
回答 1查看 155关注 0票数 1

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

下面是我已经拥有的代码,省略了boost::cycle_canceling-part,因为我的程序在到达函数之前就死了。

代码语言:javascript
复制
    #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;
    };

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

代码语言:javascript
复制
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

作为流程图:

我的程序在push_relabel_max_flow-function中声明。以下是完整的错误代码(在运行时中打印):

代码语言:javascript
复制
    /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.

在消息的末尾,您可以看到断言: algo.is_optimal()失败了。我完全不知道这意味着什么。

在源文件(boost/graph/push_relabel_max_ file . the )中,它被定义为:

代码语言:javascript
复制
bool is_optimal() {
        // check if mincut is saturated...
        global_distance_update();
        return get(distance, src) >= n;
      }

我在谷歌上搜索过却什么都没找到。我用错误的方式传递参数了吗?这是因为我使用double作为容量(但是,如果我没有记错的话,"文档“描述了使用double作为容量的可能性)?此外,我在文档中发现了这句话:

CapacityEdgeMap参数上限必须将E中的每个边映射为正数,和E^T中的每个边映射到0

大胆的部分意味着什么?这是否意味着我必须将从接收器顶点到0的所有输出边的容量设置为0?

EN

回答 1

Stack Overflow用户

发布于 2016-06-07 13:46:54

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

所以你需要:

代码语言:javascript
复制
auto edge = boost::edge(i,j,g).first;
g[edge].reverse = edges[i][j];
g[edges[i][j]].capacity = 0;

但我不知道为什么。在查看dimacs.hpp时,我注意到它们创建了它们的反向边,并给它们提供了0的容量。约3/4的方式下一页:

代码语言:javascript
复制
capacity[e1] = cap;
capacity[e2] = 0;
reverse_edge[e1] = e2;
reverse_edge[e2] = e1;

如果没有这个约束,该算法将尝试将这些作为法线边缘处理。您引用的文档中的部分描述了这一点,但并不是完全显而易见。

该算法对输入图和属性映射参数有几个特殊的要求。首先,表示网络的有向图G=(V,E)必须扩展为包含E中每条边的反向边,即输入图应该是Gin = (V,{ E ^T})。ReverseEdgeMap自变量rev必须将原图中的每一条边映射到它的反向边,即E中所有(u,v)的所有(u,v)的(u,v) -> (v,u)。CapacityEdgeMap参数上限必须将E中的每一条边映射为正数,E^T中的每一条边映射到0。

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

附带注意:在long中将double更改为推拉实例非常好。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/37624480

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档