#ifndef LIGHTNING_PLUGINS_ASKRENE_ALGORITHM_H #define LIGHTNING_PLUGINS_ASKRENE_ALGORITHM_H /* Implementation of network algorithms: shortests path, minimum cost flow, etc. */ #include "config.h" #include /* Search any path from source to destination using Breadth First Search. * * input: * @ctx: tal allocator, * @graph: graph of the network, * @source: source node, * @destination: destination node, * @capacity: arcs capacity * @cap_threshold: an arc i is traversable if capacity[i]>=cap_threshold * * output: * @prev: prev[i] is the arc that leads to node i for an optimal solution, it * @return: true if the destination node was reached. * * precondition: * |capacity|=graph_max_num_arcs * |prev|=graph_max_num_nodes * * The destination is only used as a stopping condition, if destination is * passed with an invalid idx then the algorithm will produce a discovery tree * of all reacheable nodes from the source. * */ bool BFS_path(const tal_t *ctx, const struct graph *graph, const struct node source, const struct node destination, const s64 *capacity, const s64 cap_threshold, struct arc *prev); /* Computes the distance from the source to every other node in the network * using Dijkstra's algorithm. * * input: * @ctx: tal context for internal allocation * @graph: topological information of the graph * @source: source node * @destination: destination node * @prune: if prune is true the algorithm stops when the optimal path is found * for the destination node * @capacity: arcs capacity * @cap_threshold: an arc i is traversable if capacity[i]>=cap_threshold * @cost: arc's cost * @potential: nodes' potential, ie. reduced cost for an arc * c_ij = cost_ij - potential[i] + potential[j] * * output: * @prev: for each node, this is the arc that was used to arrive to it, this can * be used to reconstruct the path from the destination to the source, * @distance: node's best distance * returns true if an optimal path is found for the destination, false otherwise * * precondition: * |capacity|=|cost|=graph_max_num_arcs * |prev|=|distance|=graph_max_num_nodes * cost[i]>=0 * if prune is true the destination must be valid * */ bool dijkstra_path(const tal_t *ctx, const struct graph *graph, const struct node source, const struct node destination, bool prune, const s64 *capacity, const s64 cap_threshold, const s64 *cost, const s64 *potential, struct arc *prev, s64 *distance); /* Finds any flow that satisfy the capacity constraints: * flow[i] <= capacity[i] * and supply/demand constraints: * supply[source] = demand[destination] = amount * supply/demand[node] = 0 for every other node * * It uses simple augmenting paths algorithm. * * input: * @ctx: tal context for internal allocation * @graph: topological information of the graph * @source: source node * @destination: destination node * @capacity: arcs capacity * @amount: supply/demand * * output: * @capacity: residual capacity * returns true if the balance constraint can be satisfied * * precondition: * |capacity|=graph_max_num_arcs * amount>=0 * */ bool simple_feasibleflow(const tal_t *ctx, const struct graph *graph, const struct node source, const struct node destination, s64 *capacity, s64 amount); /* Computes the balance of a node, ie. the incoming flows minus the outgoing. * * @graph: topology * @node: node * @capacity: capacity in the residual sense, not the constrain capacity * * This works because in the adjacency list an arc wich is dual is associated * with an inconming arc i, then we add this flow, while an arc which is not * dual corresponds to and outgoing flow that we need to substract. * The flow on the arc i (not dual) is computed as: * flow[i] = residual_capacity[i_dual], * while the constrain capacity is * capacity[i] = residual_capacity[i] + residual_capacity[i_dual] */ s64 node_balance(const struct graph *graph, const struct node node, const s64 *capacity); /* Finds the minimum cost flow that satisfy the capacity constraints: * flow[i] <= capacity[i] * and supply/demand constraints: * supply[source] = demand[destination] = amount * supply/demand[node] = 0 for every other node * * It uses successive shortest path algorithm. * * input: * @ctx: tal context for internal allocation * @graph: topological information of the graph * @source: source node * @destination: destination node * @capacity: arcs capacity * @amount: desired balance at the destination * @cost: cost per unit of flow * * output: * @capacity: residual capacity * returns true if the balance constraint can be satisfied * * precondition: * |capacity|=graph_max_num_arcs * |cost|=graph_max_num_arcs * amount>=0 * */ bool simple_mcf(const tal_t *ctx, const struct graph *graph, const struct node source, const struct node destination, s64 *capacity, s64 amount, const s64 *cost); /* Compute the cost of a flow in the network. * * @graph: network topology * @capacity: residual capacity (encodes the flow) * @cost: cost per unit of flow */ s64 flow_cost(const struct graph *graph, const s64 *capacity, const s64 *cost); /* Take an existent flow and find an optimal redistribution: * * inputs: * @ctx: tal context for internal allocation, * @graph: topological information of the graph, * @excess: supply/demand of nodes, * @capacity: residual capacity in the arcs, * @cost: cost per unit of flow for every arc, * @potential: node potential, * * outputs: * @excess: all values become zero if there exist a feasible solution, * @capacity: encodes the resulting flow, * @potential: the potential that proves the solution using the complementary * slackness optimality condition. * */ bool mcf_refinement(const tal_t *ctx, const struct graph *graph, s64 *excess, s64 *capacity, const s64 *cost, s64 *potential); #endif /* LIGHTNING_PLUGINS_ASKRENE_ALGORITHM_H */