38static void check_cycles(
graph_t * g);
41#define LENGTH(e) (ND_rank(aghead(e)) - ND_rank(agtail(e)))
42#define SLACK(e) (LENGTH(e) - ED_minlen(e))
43#define SEQ(a,b,c) ((a) <= (b) && (b) <= (c))
44#define TREE_EDGE(e) (ED_tree_index(e) >= 0)
62 agerrorf(
"add_tree_edge: missing tree edge\n");
65 assert(edge_list_size(&ctx->
Tree_edge) <= INT_MAX);
73 agerrorf(
"add_tree_edge: empty outedge list\n");
81 agerrorf(
"add_tree_edge: empty inedge list\n");
105 agerrorf(
"invalidate_path: skipped over LCA\n");
126 for (j = 0; j <= i; j++)
133 for (j = 0; j <= i; j++)
154 node_queue_t Q = {0};
155 node_queue_reserve(&Q, ctx->
N_nodes);
160 node_queue_push_back(&Q, v);
163 while (!node_queue_is_empty(&Q)) {
164 node_t *
const v = node_queue_pop_front(&Q);
167 for (
int i = 0; (e =
ND_in(v).list[i]); i++)
169 for (
int i = 0; (e =
ND_out(v).list[i]); i++) {
171 node_queue_push_back(&Q,
aghead(e));
203 while (ctx->
S_i < j) {
225 node_list_t todo = {0};
226 node_list_append(&todo, v);
228 while (!node_list_is_empty(&todo)) {
229 v = node_list_pop_back(&todo);
231 for (i = 0; (e =
ND_out(v).list[i]); i++) {
235 if (slack < Slack || Enter ==
NULL) {
241 node_list_append(&todo,
aghead(e));
243 for (i = 0; (e =
ND_tree_in(v).list[i]) && Slack > 0; i++)
245 node_list_append(&todo,
agtail(e));
248 node_list_free(&todo);
260 node_list_t todo = {0};
261 node_list_append(&todo, v);
263 while (!node_list_is_empty(&todo)) {
264 v = node_list_pop_back(&todo);
266 for (i = 0; (e =
ND_in(v).list[i]); i++) {
270 if (slack < Slack || Enter ==
NULL) {
276 node_list_append(&todo,
agtail(e));
278 for (i = 0; (e =
ND_tree_out(v).list[i]) && Slack > 0; i++)
280 node_list_append(&todo,
aghead(e));
283 node_list_free(&todo);
313#define ND_subtree(n) (subtree_t*)ND_par(n)
314#define ND_subtree_set(n,value) (ND_par(n) = (edge_t*)value)
349 tsts_push_back(&todo, (
tst_t){.v = v, .rv = 1});
351 while (!tsts_is_empty(&todo)) {
352 bool updated =
false;
359 (void)tsts_pop_back(&todo);
360 if (tsts_is_empty(&todo)) {
363 --tsts_back(&todo)->rv;
368 tsts_push_back(&todo, next);
382 (void)tsts_pop_back(&todo);
383 if (tsts_is_empty(&todo)) {
386 --tsts_back(&todo)->rv;
391 tsts_push_back(&todo, next);
402 if (tsts_is_empty(&todo)) {
405 tsts_back(&todo)->rv +=
last.rv;
436 while (s0->
par && s0->
par != s0) {
447 for (r0 = s0; r0->
par && r0->
par != r0; r0 = r0->
par);
448 for (r1 =
s1; r1->
par && r1->
par != r1; r1 = r1->
par);
449 if (r0 == r1)
return r0;
453 else if (r1->
size < r0->
size) r = r0;
468 if (best &&
SLACK(best) == 0)
return best;
469 for (i = 0; (e =
ND_out(v).list[i]); i++) {
471 if (
aghead(e) == from)
continue;
476 if (best == 0 ||
SLACK(e) <
SLACK(best)) best = e;
482 for (i = 0; (e =
ND_in(v).list[i]); i++) {
484 if (
agtail(e) == from)
continue;
489 if (best == 0 ||
SLACK(e) <
SLACK(best)) best = e;
508 const size_t left = 2 * (i + 1) - 1;
509 const size_t right = 2 * (i + 1);
511 if (left < heap->size && elt[
left]->size < elt[smallest]->size) smallest =
left;
512 if (right < heap->size && elt[
right]->size < elt[smallest]->size) smallest =
right;
514 SWAP(&elt[i], &elt[smallest]);
520 }
while (i < heap->size);
527 for (
size_t i = 0; i <
heap->size; i++)
heap->elt[i]->heap_index = i;
541 heap->elt[0]->heap_index = 0;
555 for (i = 0; (e =
ND_tree_in(v).list[i]); i++) {
605 size_t subtree_count = 0;
645 for (
size_t i = 0; i < subtree_count; i++)
free(
tree[i]);
722 agerrorf(
"update: mismatched lca in treeupdates\n");
727 int lca_low =
ND_low(lca);
741 int Minrank = INT_MAX;
742 int Maxrank = INT_MIN;
776 for (
size_t i = 0; i < edge_list_size(&ctx->
Tree_edge); i++) {
799#pragma GCC diagnostic push
800#pragma GCC diagnostic ignored "-Wcast-qual"
805#pragma GCC diagnostic pop
824 int low, high, choice;
825 int inweight, outweight;
832 assert(Maxrank >= 0);
833 int *nrank =
gv_calloc((
size_t)Maxrank + 1,
sizeof(
int));
834 if ( (
s =
agget(ctx->
G,
"TBbalance")) ) {
835 if (
streq(
s,
"min")) adj = 1;
836 else if (
streq(
s,
"max")) adj = 2;
839 if (
ND_in(n).size == 0 && adj == 1) {
842 if (
ND_out(n).size == 0 && adj == 2) {
847 node_list_t Tree_node = {0};
848 node_list_reserve(&Tree_node, ctx->
N_nodes);
850 node_list_append(&Tree_node, n);
852 node_list_sort(&Tree_node,
854 for (
size_t i = 0; i < node_list_size(&Tree_node); i++) {
855 n = node_list_get(&Tree_node, i);
859 for (
size_t ii = 0; ii < node_list_size(&Tree_node); ii++) {
860 n = node_list_get(&Tree_node, ii);
863 inweight = outweight = 0;
866 for (
size_t i = 0; (e =
ND_in(n).list[i]); i++) {
870 for (
size_t i = 0; (e =
ND_out(n).list[i]); i++) {
877 if (inweight == outweight)
878 ND_rank(n) = (adj == 1? low : high);
881 if (inweight == outweight) {
883 for (
int i = low + 1; i <= high; i++)
884 if (nrank[i] < nrank[choice])
895 node_list_free(&Tree_node);
908 for (
size_t i = 0; (e =
ND_out(n).list[i]); i++)
914 bool feasible =
true;
918 for (i = 0; (e =
ND_in(n).list[i]); i++) {
927 for (i = 0; (e =
ND_out(n).list[i]); i++);
945 for (
size_t i = 0; (e =
ND_out(n).list[i]); i++) {
968 char *ns =
"network simplex: ";
979 " edges maxiter=%d balance=%d\n", ns, nn, ne, maxiter, balance);
986 if (search_size >= 0)
1012 if (
Verbose && iter % 100 == 0) {
1013 if (iter % 1000 == 100)
1015 fprintf(stderr,
"%d ", iter);
1016 if (iter % 1000 == 0)
1017 fputc(
'\n', stderr);
1019 if (iter >= maxiter)
1037 fputc(
'\n', stderr);
1049 if ((
s =
agget(g,
"searchsize")))
1050 search_size = atoi(
s);
1054 return rank2 (g, balance, maxiter, search_size);
1074 for (i = 0; (e =
ND_out(v).list[i]); i++)
1076 agerrorf(
"overflow when computing edge weight sum\n");
1079 for (i = 0; (e =
ND_in(v).list[i]); i++)
1081 agerrorf(
"overflow when computing edge weight sum\n");
1133 for (i = 0; (e =
ND_tree_in(v).list[i]); i++)
1160 dfs_stack_t todo = {0};
1165 dfs_stack_push_back(&todo, root);
1167 while (!dfs_stack_is_empty(&todo)) {
1168 bool pushed_new =
false;
1179 dfs_stack_push_back(&todo, next);
1196 dfs_stack_push_back(&todo, next);
1208 (void)dfs_stack_pop_back(&todo);
1210 if (!dfs_stack_is_empty(&todo)) {
1211 dfs_stack_back(&todo)->lim = lim + 1;
1215 dfs_stack_free(&todo);
1231 dfs_stack_t todo = {0};
1235 const dfs_state_t root = {.
v = v, .par = par, .lim = low};
1236 dfs_stack_push_back(&todo, root);
1238 while (!dfs_stack_is_empty(&todo)) {
1239 bool processed_child =
false;
1253 dfs_stack_push_back(&todo, next);
1255 processed_child =
true;
1259 if (processed_child) {
1274 dfs_stack_push_back(&todo, next);
1276 processed_child =
true;
1280 if (processed_child) {
1287 (void)dfs_stack_pop_back(&todo);
1289 if (!dfs_stack_is_empty(&todo)) {
1290 dfs_stack_back(&todo)->lim = lim + 1;
1294 dfs_stack_free(&todo);
1313 fprintf(stderr,
"not a tight tree %p", e);
1316 if (e_cnt != edge_list_size(&ctx->
Tree_edge))
1317 fprintf(stderr,
"something missing\n");
1320void check_fast_node(
node_t * n)
1324 while (nptr && nptr != n)
1326 assert(nptr !=
NULL);
1329static void dump_node(FILE *sink,
node_t *n) {
1331 fprintf(sink,
"%p", n);
1337static void dump_graph (
graph_t* g)
1342 FILE* fp = fopen (
"ns.gv",
"w");
1343 fprintf (fp,
"digraph \"%s\" {\n",
agnameof(g));
1350 for (i = 0; (e =
ND_out(n).list[i]); i++) {
1355 fputs(
" -> \"", fp);
1361 fprintf (fp,
"}\n");
1375 for (i = 0; (e =
ND_out(n).list[i]); i++) {
1379 fprintf(stderr,
"cycle: last edge %" PRIx64
" %s(%" PRIx64
") %s(%" PRIx64
1388 fprintf(stderr,
"unwind %" PRIx64
" %s(%" PRIx64
")\n", (uint64_t)e,
1390 if (x != n)
return x;
1391 fprintf(stderr,
"unwound to root\n");
static agxbuf last
last message
Memory allocation wrappers that exit on failure.
static void * gv_calloc(size_t nmemb, size_t size)
static void * gv_alloc(size_t size)
static NORETURN void graphviz_exit(int status)
static int cnt(Dict_t *d, Dtlink_t **set)
char * agget(void *obj, char *name)
void agerrorf(const char *fmt,...)
int agerr(agerrlevel_t level, const char *fmt,...)
Agnode_t * agnxtnode(Agraph_t *g, Agnode_t *n)
Agnode_t * agfstnode(Agraph_t *g)
Agraph_t * agraphof(void *obj)
char * agnameof(void *)
returns a string descriptor for the object.
Arithmetic helper functions.
static Agedge_t * top(edge_stack_t *sp)
#define DEFINE_LIST(name, type)
NEATOPROCS_API void s1(graph_t *, node_t *)
static void TB_balance(network_simplex_ctx_t *ctx)
static subtree_t * merge_trees(network_simplex_ctx_t *ctx, Agedge_t *e)
static int x_val(edge_t *e, node_t *v, int dir)
static void freeTreeList(network_simplex_ctx_t *ctx, graph_t *g)
static void reset_lists(network_simplex_ctx_t *ctx)
static subtree_t * STextractmin(STheap_t *heap)
int rank(graph_t *g, int balance, int maxiter)
static int dfs_range(node_t *v, edge_t *par, int low)
static int update(network_simplex_ctx_t *ctx, edge_t *e, edge_t *f)
static void LR_balance(network_simplex_ctx_t *ctx)
static int tight_subtree_search(network_simplex_ctx_t *ctx, Agnode_t *v, subtree_t *st)
a stack of states
static void dfs_cutval(node_t *v, edge_t *par)
static bool on_heap(const subtree_t *tree)
is this subtree stored in an STheap?
static edge_t * dfs_enter_outedge(node_t *v, int Low, int Lim)
static size_t STheapsize(const STheap_t *heap)
static void init_cutvalues(network_simplex_ctx_t *ctx)
static STheap_t * STbuildheap(subtree_t **elt, size_t size)
static edge_t * enter_edge(edge_t *e)
#define ND_subtree_set(n, value)
static void init_rank(network_simplex_ctx_t *ctx)
static void exchange_tree_edges(network_simplex_ctx_t *ctx, edge_t *e, edge_t *f)
static int feasible_tree(network_simplex_ctx_t *ctx)
static Agnode_t * treeupdate(Agnode_t *v, Agnode_t *w, int cutvalue, int dir)
static int increasingrankcmpf(const node_t **x, const node_t **y)
static subtree_t * STsetFind(Agnode_t *n0)
static void rerank(Agnode_t *v, int delta)
static int dfs_range_init(node_t *v)
struct subtree_s subtree_t
static void x_cutval(edge_t *f)
static int scan_and_normalize(network_simplex_ctx_t *ctx)
static int add_tree_edge(network_simplex_ctx_t *ctx, edge_t *e)
static Agedge_t * inter_tree_edge_search(Agnode_t *v, Agnode_t *from, Agedge_t *best)
static int decreasingrankcmpf(const node_t **x, const node_t **y)
static void invalidate_path(node_t *lca, node_t *to_node)
static edge_t * leave_edge(network_simplex_ctx_t *ctx)
static subtree_t * find_tight_subtree(network_simplex_ctx_t *ctx, Agnode_t *v)
static void tree_adjust(Agnode_t *v, Agnode_t *from, int delta)
static bool init_graph(network_simplex_ctx_t *ctx, graph_t *g)
static subtree_t * STsetUnion(subtree_t *s0, subtree_t *s1)
static void STheapify(STheap_t *heap, size_t i)
static void graphSize(graph_t *g, size_t *nn, size_t *ne)
static edge_t * dfs_enter_inedge(node_t *v, int Low, int Lim)
int rank2(graph_t *g, int balance, int maxiter, int search_size)
static Agedge_t * inter_tree_edge(subtree_t *tree)
arithmetic overflow helpers
static bool sadd_overflow(int a, int b, int *res)
static int nedges
total no. of edges used in routing
static bool streq(const char *a, const char *b)
are a and b equal?
local state used by dfs_range*
size_t heap_index
required to find non-min elts when merged
state for use in tight_subtree_search
int out_i
iteration counter through ND_out(v).list
int in_i
iteration counter through ND_in(v).list