40static void check_cycles(
graph_t *g);
43#define LENGTH(e) (ND_rank(aghead(e)) - ND_rank(agtail(e)))
44#define SLACK(e) (LENGTH(e) - ED_minlen(e))
45#define SEQ(a, b, c) ((a) <= (b) && (b) <= (c))
46#define TREE_EDGE(e) (ED_tree_index(e) >= 0)
52 size_t N_edges, N_nodes;
60 agerrorf(
"add_tree_edge: missing tree edge\n");
63 assert(
LIST_SIZE(&ctx->Tree_edge) <= INT_MAX);
71 agerrorf(
"add_tree_edge: empty outedge list\n");
79 agerrorf(
"add_tree_edge: empty inedge list\n");
103 agerrorf(
"invalidate_path: skipped over LCA\n");
124 for (j = 0; j <= i; j++)
131 for (j = 0; j <= i; j++)
161 for (
int i = 0; (e =
ND_in(v).list[i]); i++)
163 for (
int i = 0; (e =
ND_out(v).list[i]); i++) {
168 if (ctr != ctx->N_nodes) {
182 while (ctx->S_i <
LIST_SIZE(&ctx->Tree_edge)) {
188 rv =
LIST_GET(&ctx->Tree_edge, ctx->S_i);
189 if (++
cnt >= ctx->Search_size)
196 while (ctx->S_i < j) {
202 rv =
LIST_GET(&ctx->Tree_edge, ctx->S_i);
203 if (++
cnt >= ctx->Search_size)
223 for (
int i = 0; (e =
ND_out(v).list[i]); i++) {
226 const int slack =
SLACK(e);
227 if (slack < Slack || Enter ==
NULL) {
235 for (
int i = 0; (e =
ND_tree_in(v).list[i]) && Slack > 0; i++)
256 for (
int i = 0; (e =
ND_in(v).list[i]); i++) {
259 const int slack =
SLACK(e);
260 if (slack < Slack || Enter ==
NULL) {
268 for (
int i = 0; (e =
ND_tree_out(v).list[i]) && Slack > 0; i++)
302#define ND_subtree(n) (subtree_t *)ND_par(n)
303#define ND_subtree_set(n, value) (ND_par(n) = (edge_t *)value)
337 bool updated =
false;
422 while (s0->
par && s0->
par != s0) {
434 for (r0 = s0; r0->
par && r0->
par != r0; r0 = r0->
par)
436 for (r1 =
s1; r1->
par && r1->
par != r1; r1 = r1->
par)
475 if (
s->out_i == 0 &&
s->in_i == 0 && best !=
NULL &&
SLACK(best) == 0) {
480 bool updated =
false;
482 for (; (e =
ND_out(
s->v).list[
s->out_i]) !=
NULL; ++
s->out_i) {
506 for (; (e =
ND_in(
s->v).list[
s->in_i]); ++
s->in_i) {
543 const size_t left = 2 * (i + 1) - 1;
544 const size_t right = 2 * (i + 1);
546 if (left < heap->size && elt[
left]->size < elt[smallest]->size)
548 if (right < heap->size && elt[
right]->size < elt[smallest]->size)
551 SWAP(&elt[i], &elt[smallest]);
557 }
while (i < heap->size);
564 for (
size_t i = 0; i <
heap->size; i++)
565 heap->elt[i]->heap_index = i;
576 heap->elt[0]->heap_index = 0;
591 LIST(frame_t) todo = {0};
595 bool updated =
false;
598 if (
top->in_i == 0 &&
top->out_i == 0) {
605 if (w !=
top->from) {
617 if (w !=
top->from) {
663 size_t subtree_count = 0;
703 for (
size_t i = 0; i < subtree_count; i++)
708 assert(
LIST_SIZE(&ctx->Tree_edge) == ctx->N_nodes - 1);
717 const bool d = v ==
agtail(e) ? dir : !dir;
743 bool updated =
false;
746 if (
top->out_i == 0 &&
top->in_i == 0) {
806 agerrorf(
"update: mismatched lca in treeupdates\n");
811 int lca_low =
ND_low(lca);
823 int Minrank = INT_MAX;
824 int Maxrank = INT_MIN;
851 for (
size_t i = 0; i <
LIST_SIZE(&ctx->Tree_edge); i++) {
893 assert(Maxrank >= 0);
894 int *nrank =
gv_calloc((
size_t)Maxrank + 1,
sizeof(
int));
895 if ((
s =
agget(ctx->
G,
"TBbalance"))) {
903 if (
ND_in(n).size == 0 && adj == 1) {
906 if (
ND_out(n).size == 0 && adj == 2) {
917 for (
size_t i = 0; i <
LIST_SIZE(&Tree_node); i++) {
922 for (
size_t ii = 0; ii <
LIST_SIZE(&Tree_node); ii++) {
930 for (
size_t i = 0; (e =
ND_in(n).list[i]); i++) {
934 for (
size_t i = 0; (e =
ND_out(n).list[i]); i++) {
941 if (inweight == outweight)
942 ND_rank(n) = adj == 1 ? low : high;
944 if (inweight == outweight) {
946 for (
int i = low + 1; i <= high; i++)
947 if (nrank[i] < nrank[choice])
969 for (
size_t i = 0;
ND_out(n).list[i]; i++)
975 bool feasible =
true;
979 for (i = 0; (e =
ND_in(n).list[i]); i++) {
988 for (i = 0;
ND_out(n).list[i]; i++)
1004 for (
size_t i = 0;
ND_out(n).list[i]; i++) {
1026 char ns[] =
"network simplex: ";
1038 " edges maxiter=%d balance=%d\n",
1039 ns, nn, ne, maxiter, balance);
1046 if (search_size >= 0)
1047 ctx.Search_size = search_size;
1071 if (
Verbose && iter % 100 == 0) {
1072 if (iter % 1000 == 100)
1074 fprintf(stderr,
"%d ", iter);
1075 if (iter % 1000 == 0)
1076 fputc(
'\n', stderr);
1078 if (iter >= maxiter)
1096 fputc(
'\n', stderr);
1099 ns, ctx.N_nodes, ctx.N_edges, iter,
elapsed_sec());
1108 if ((
s =
agget(g,
"searchsize")))
1109 search_size = atoi(
s);
1113 return rank2(g, balance, maxiter, search_size);
1132 for (
int i = 0; (e =
ND_out(v).list[i]); i++)
1134 agerrorf(
"overflow when computing edge weight sum\n");
1137 for (
int i = 0; (e =
ND_in(v).list[i]); i++)
1139 agerrorf(
"overflow when computing edge weight sum\n");
1197 bool updated =
false;
1200 if (e !=
top->par) {
1212 if (e !=
top->par) {
1258 bool pushed_new =
false;
1324 const dfs_state_t root = {.
v = v, .par = par, .lim = low};
1328 bool processed_child =
false;
1344 processed_child =
true;
1348 if (processed_child) {
1365 processed_child =
true;
1369 if (processed_child) {
1396 for (
int i = 0; (e =
ND_tree_out(n).list[i]); i++) {
1399 fprintf(stderr,
"not a tight tree %p", e);
1402 if (e_cnt !=
LIST_SIZE(&ctx->Tree_edge))
1403 fprintf(stderr,
"something missing\n");
1406static void dump_node(FILE *sink,
node_t *n) {
1408 fprintf(sink,
"%p", n);
1413static void dump_graph(
graph_t *g) {
1415 FILE *
const fp = fopen(
"ns.gv",
"w");
1416 fprintf(fp,
"digraph \"%s\" {\n",
agnameof(g));
1423 for (
int i = 0; (e =
ND_out(n).list[i]); i++) {
1428 fputs(
" -> \"", fp);
1445 for (
int i = 0; (e =
ND_out(n).list[i]); i++) {
1449 fprintf(stderr,
"cycle: last edge %p %s(%p) %s(%p)\n", e,
agnameof(n), n,
1454 node_t *
const x = checkdfs(g, w);
1456 fprintf(stderr,
"unwind %p %s(%p)\n", e,
agnameof(n), n);
1459 fprintf(stderr,
"unwound to root\n");
1471void check_cycles(
graph_t *g) {
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)
char * agnameof(void *)
returns a string descriptor for the object.
Arithmetic helper functions.
static Agedge_t * top(edge_stack_t *sp)
type-generic dynamically expanding list
#define LIST_PUSH_BACK(list,...)
#define LIST_APPEND(list,...)
#define LIST_POP_FRONT(list)
#define LIST_DROP_BACK(list)
#define LIST_RESERVE(list, capacity)
#define LIST_POP_BACK(list)
#define LIST_SORT(list, cmp)
#define LIST_SET(list, index, item)
#define LIST_IS_EMPTY(list)
#define LIST_GET(list, index)
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 increasingrankcmpf(const void *x, const void *y)
static int tight_subtree_search(network_simplex_ctx_t *ctx, Agnode_t *v, subtree_t *st)
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 Agnode_t * treeupdate(Agnode_t *v, Agnode_t *w, int cutvalue, bool dir)
static void init_cutvalues(network_simplex_ctx_t *ctx)
static Agedge_t * inter_tree_edge_search(Agnode_t *v)
static STheap_t * STbuildheap(subtree_t **elt, size_t size)
static edge_t * enter_edge(edge_t *e)
static int decreasingrankcmpf(const void *x, const void *y)
#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 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 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, 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 int sadd_saturate(int a, int b)
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*
information the ID allocator needs to do its job
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