Я пытаюсь реализовать программу, которая обнаруживает возможности arbitrage trading с использованием минимального расхода . алгоритм. Этот алгоритм реализован в Boost.Graph в виде boost::push_relabel_max_flow()
, за которым следует звонок boost::cycle_canceling()
.Boost.Graph - algo.is_optimal() assert
Ниже приведен код, который у меня уже есть, оставляя boost::cycle_canceling
-part, потому что моя программа умирает до достижения функции.
#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
В блок-схеме:
Моя программа утверждает в 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.
В самом конце сообщения вы можете увидеть утверждение: algo.is_optimal() не. Я совершенно не знаю, что это значит.
В исходном файле (подталкивания/график/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:
Аргумент крышка CapacityEdgeMap должен отображать каждое ребро в Е к положительному числа, и каждому ребру Х^Т к 0.
Что означает жирная часть? Означает ли это, что мне нужно установить емкость всех исходящих ребер из вершины-вершины в 0?
Я не знаком с этим конкретным алгоритмом. Я запустил код, хотя и похоже, что 'is_optimal' является частью алгоритма push-relabel, который не увеличивается, как я думал изначально. Я предполагаю, что это может иметь отношение к топологии вашего графика. У меня не было времени, чтобы пройти через код построения графика. Вы уверены, что эта топология верна для такого типа проблем? Вы можете подумать о том, чтобы смотреть с минимальным рабочим примером алгоритма. – pbible
Я отредактировал мой пост с дополнительной информацией и диаграммой. Я уверен, что могу использовать этот алгоритм для своего графика. – Bobface