rank.c 24 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043
  1. /*************************************************************************
  2. * Copyright (c) 2011 AT&T Intellectual Property
  3. * All rights reserved. This program and the accompanying materials
  4. * are made available under the terms of the Eclipse Public License v1.0
  5. * which accompanies this distribution, and is available at
  6. * https://www.eclipse.org/legal/epl-v10.html
  7. *
  8. * Contributors: Details at https://graphviz.org
  9. *************************************************************************/
  10. /*
  11. * Rank the nodes of a directed graph, subject to user-defined
  12. * sets of nodes to be kept on the same, min, or max rank.
  13. * The temporary acyclic fast graph is constructed and ranked
  14. * by a network-simplex technique. Then ranks are propagated
  15. * to non-leader nodes and temporary edges are deleted.
  16. * Leaf nodes and top-level clusters are left collapsed, though.
  17. * Assigns global minrank and maxrank of graph and all clusters.
  18. *
  19. * TODO: safety code. must not be in two clusters at same level.
  20. * must not be in same/min/max/rank and a cluster at the same time.
  21. * watch out for interactions between leaves and clusters.
  22. */
  23. #include <cgraph/gv_math.h>
  24. #include <dotgen/dot.h>
  25. #include <limits.h>
  26. #include <stdbool.h>
  27. #include <stddef.h>
  28. #include <stdint.h>
  29. #include <util/alloc.h>
  30. static void dot1_rank(graph_t *g);
  31. static void dot2_rank(graph_t *g);
  32. static void
  33. renewlist(elist * L)
  34. {
  35. for (size_t i = L->size; i != SIZE_MAX; i--)
  36. L->list[i] = NULL;
  37. L->size = 0;
  38. }
  39. static void
  40. cleanup1(graph_t * g)
  41. {
  42. node_t *n;
  43. edge_t *e, *f;
  44. for (size_t c = 0; c < GD_comp(g).size; c++) {
  45. GD_nlist(g) = GD_comp(g).list[c];
  46. for (n = GD_nlist(g); n; n = ND_next(n)) {
  47. renewlist(&ND_in(n));
  48. renewlist(&ND_out(n));
  49. ND_mark(n) = false;
  50. }
  51. }
  52. for (n = agfstnode(g); n; n = agnxtnode(g, n)) {
  53. for (e = agfstout(g, n); e; e = agnxtout(g, e)) {
  54. f = ED_to_virt(e);
  55. /* Null out any other references to f to make sure we don't
  56. * handle it a second time. For example, parallel multiedges
  57. * share a virtual edge.
  58. */
  59. if (f && (e != ED_to_orig(f))) {
  60. ED_to_virt(e) = NULL;
  61. }
  62. }
  63. }
  64. for (n = agfstnode(g); n; n = agnxtnode(g, n)) {
  65. for (e = agfstout(g, n); e; e = agnxtout(g, e)) {
  66. f = ED_to_virt(e);
  67. if (f && ED_to_orig(f) == e) {
  68. free(f->base.data);
  69. free(f);
  70. ED_to_virt(e) = NULL;
  71. }
  72. }
  73. }
  74. free(GD_comp(g).list);
  75. GD_comp(g).list = NULL;
  76. GD_comp(g).size = 0;
  77. }
  78. /* When there are edge labels, extra ranks are reserved here for the virtual
  79. * nodes of the labels. This is done by doubling the input edge lengths.
  80. * The input rank separation is adjusted to compensate.
  81. */
  82. static void
  83. edgelabel_ranks(graph_t * g)
  84. {
  85. node_t *n;
  86. edge_t *e;
  87. if (GD_has_labels(g) & EDGE_LABEL) {
  88. for (n = agfstnode(g); n; n = agnxtnode(g, n))
  89. for (e = agfstout(g, n); e; e = agnxtout(g, e))
  90. ED_minlen(e) *= 2;
  91. GD_ranksep(g) = (GD_ranksep(g) + 1) / 2;
  92. }
  93. }
  94. /* Merge the nodes of a min, max, or same rank set. */
  95. static void
  96. collapse_rankset(graph_t * g, graph_t * subg, int kind)
  97. {
  98. node_t *u, *v;
  99. u = v = agfstnode(subg);
  100. if (u) {
  101. ND_ranktype(u) = kind;
  102. while ((v = agnxtnode(subg, v))) {
  103. UF_union(u, v);
  104. ND_ranktype(v) = ND_ranktype(u);
  105. }
  106. switch (kind) {
  107. case MINRANK:
  108. case SOURCERANK:
  109. if (GD_minset(g) == NULL)
  110. GD_minset(g) = u;
  111. else
  112. GD_minset(g) = UF_union(GD_minset(g), u);
  113. break;
  114. case MAXRANK:
  115. case SINKRANK:
  116. if (GD_maxset(g) == NULL)
  117. GD_maxset(g) = u;
  118. else
  119. GD_maxset(g) = UF_union(GD_maxset(g), u);
  120. break;
  121. }
  122. switch (kind) {
  123. case SOURCERANK:
  124. ND_ranktype(GD_minset(g)) = kind;
  125. break;
  126. case SINKRANK:
  127. ND_ranktype(GD_maxset(g)) = kind;
  128. break;
  129. }
  130. }
  131. }
  132. static int
  133. rank_set_class(graph_t * g)
  134. {
  135. static char *name[] = { "same", "min", "source", "max", "sink", NULL };
  136. static int class[] =
  137. { SAMERANK, MINRANK, SOURCERANK, MAXRANK, SINKRANK, 0 };
  138. int val;
  139. if (is_cluster(g))
  140. return CLUSTER;
  141. val = maptoken(agget(g, "rank"), name, class);
  142. GD_set_type(g) = val;
  143. return val;
  144. }
  145. static int
  146. make_new_cluster(graph_t * g, graph_t * subg)
  147. {
  148. int cno;
  149. cno = ++(GD_n_cluster(g));
  150. GD_clust(g) = gv_recalloc(GD_clust(g), GD_n_cluster(g), cno + 1,
  151. sizeof(graph_t*));
  152. GD_clust(g)[cno] = subg;
  153. do_graph_label(subg);
  154. return cno;
  155. }
  156. static void
  157. node_induce(graph_t * par, graph_t * g)
  158. {
  159. node_t *n, *nn;
  160. edge_t *e;
  161. int i;
  162. /* enforce that a node is in at most one cluster at this level */
  163. for (n = agfstnode(g); n; n = nn) {
  164. nn = agnxtnode(g, n);
  165. if (ND_ranktype(n)) {
  166. agdelete(g, n);
  167. continue;
  168. }
  169. for (i = 1; i < GD_n_cluster(par); i++)
  170. if (agcontains(GD_clust(par)[i], n))
  171. break;
  172. if (i < GD_n_cluster(par))
  173. agdelete(g, n);
  174. ND_clust(n) = NULL;
  175. }
  176. for (n = agfstnode(g); n; n = agnxtnode(g, n)) {
  177. for (e = agfstout(dot_root(g), n); e; e = agnxtout(dot_root(g), e)) {
  178. if (agcontains(g, aghead(e)))
  179. agsubedge(g,e,1);
  180. }
  181. }
  182. }
  183. void
  184. dot_scan_ranks(graph_t * g)
  185. {
  186. node_t *n, *leader = NULL;
  187. GD_minrank(g) = INT_MAX;
  188. GD_maxrank(g) = -1;
  189. for (n = agfstnode(g); n; n = agnxtnode(g, n)) {
  190. if (GD_maxrank(g) < ND_rank(n))
  191. GD_maxrank(g) = ND_rank(n);
  192. if (GD_minrank(g) > ND_rank(n))
  193. GD_minrank(g) = ND_rank(n);
  194. if (leader == NULL)
  195. leader = n;
  196. else {
  197. if (ND_rank(n) < ND_rank(leader))
  198. leader = n;
  199. }
  200. }
  201. GD_leader(g) = leader;
  202. }
  203. static void
  204. cluster_leader(graph_t * clust)
  205. {
  206. node_t *leader, *n;
  207. int maxrank = 0;
  208. /* find number of ranks and select a leader */
  209. leader = NULL;
  210. for (n = GD_nlist(clust); n; n = ND_next(n)) {
  211. if (ND_rank(n) == 0 && ND_node_type(n) == NORMAL)
  212. leader = n;
  213. if (maxrank < ND_rank(n))
  214. maxrank = ND_rank(n);
  215. }
  216. assert(leader != NULL);
  217. GD_leader(clust) = leader;
  218. for (n = agfstnode(clust); n; n = agnxtnode(clust, n)) {
  219. assert(ND_UF_size(n) <= 1 || n == leader);
  220. UF_union(n, leader);
  221. ND_ranktype(n) = CLUSTER;
  222. }
  223. }
  224. /*
  225. * A cluster is collapsed in three steps.
  226. * 1) The nodes of the cluster are ranked locally.
  227. * 2) The cluster is collapsed into one node on the least rank.
  228. * 3) In class1(), any inter-cluster edges are converted using
  229. * the "virtual node + 2 edges" trick.
  230. */
  231. static void
  232. collapse_cluster(graph_t * g, graph_t * subg)
  233. {
  234. if (GD_parent(subg)) {
  235. return;
  236. }
  237. GD_parent(subg) = g;
  238. node_induce(g, subg);
  239. if (agfstnode(subg) == NULL)
  240. return;
  241. make_new_cluster(g, subg);
  242. if (CL_type == LOCAL) {
  243. dot1_rank(subg);
  244. cluster_leader(subg);
  245. } else
  246. dot_scan_ranks(subg);
  247. }
  248. /* Execute union commands for "same rank" subgraphs and clusters. */
  249. static void
  250. collapse_sets(graph_t *rg, graph_t *g)
  251. {
  252. int c;
  253. graph_t *subg;
  254. for (subg = agfstsubg(g); subg; subg = agnxtsubg(subg)) {
  255. c = rank_set_class(subg);
  256. if (c) {
  257. if ((c == CLUSTER) && CL_type == LOCAL)
  258. collapse_cluster(rg, subg);
  259. else
  260. collapse_rankset(rg, subg, c);
  261. }
  262. else collapse_sets(rg, subg);
  263. }
  264. }
  265. static void
  266. find_clusters(graph_t * g)
  267. {
  268. graph_t *subg;
  269. for (subg = agfstsubg(dot_root(g)); subg; subg = agnxtsubg(subg)) {
  270. if (GD_set_type(subg) == CLUSTER)
  271. collapse_cluster(g, subg);
  272. }
  273. }
  274. static void
  275. set_minmax(graph_t * g)
  276. {
  277. int c;
  278. GD_minrank(g) += ND_rank(GD_leader(g));
  279. GD_maxrank(g) += ND_rank(GD_leader(g));
  280. for (c = 1; c <= GD_n_cluster(g); c++)
  281. set_minmax(GD_clust(g)[c]);
  282. }
  283. /* To ensure that min and max rank nodes always have the intended rank
  284. * assignment, reverse any incompatible edges.
  285. */
  286. static point
  287. minmax_edges(graph_t * g)
  288. {
  289. node_t *n;
  290. edge_t *e;
  291. point slen;
  292. slen.x = slen.y = 0;
  293. if ((GD_maxset(g) == NULL) && (GD_minset(g) == NULL))
  294. return slen;
  295. if (GD_minset(g) != NULL)
  296. GD_minset(g) = UF_find(GD_minset(g));
  297. if (GD_maxset(g) != NULL)
  298. GD_maxset(g) = UF_find(GD_maxset(g));
  299. if ((n = GD_maxset(g))) {
  300. slen.y = (ND_ranktype(GD_maxset(g)) == SINKRANK);
  301. while ((e = ND_out(n).list[0])) {
  302. assert(aghead(e) == UF_find(aghead(e)));
  303. reverse_edge(e);
  304. }
  305. }
  306. if ((n = GD_minset(g))) {
  307. slen.x = (ND_ranktype(GD_minset(g)) == SOURCERANK);
  308. while ((e = ND_in(n).list[0])) {
  309. assert(agtail(e) == UF_find(agtail(e)));
  310. reverse_edge(e);
  311. }
  312. }
  313. return slen;
  314. }
  315. static int
  316. minmax_edges2(graph_t * g, point slen)
  317. {
  318. node_t *n;
  319. edge_t *e = 0;
  320. if ((GD_maxset(g)) || (GD_minset(g))) {
  321. for (n = agfstnode(g); n; n = agnxtnode(g, n)) {
  322. if (n != UF_find(n))
  323. continue;
  324. if ((ND_out(n).size == 0) && GD_maxset(g) && (n != GD_maxset(g))) {
  325. e = virtual_edge(n, GD_maxset(g), NULL);
  326. ED_minlen(e) = slen.y;
  327. ED_weight(e) = 0;
  328. }
  329. if ((ND_in(n).size == 0) && GD_minset(g) && (n != GD_minset(g))) {
  330. e = virtual_edge(GD_minset(g), n, NULL);
  331. ED_minlen(e) = slen.x;
  332. ED_weight(e) = 0;
  333. }
  334. }
  335. }
  336. return (e != 0);
  337. }
  338. /* Run the network simplex algorithm on each component. */
  339. void rank1(graph_t * g)
  340. {
  341. int maxiter = INT_MAX;
  342. char *s;
  343. if ((s = agget(g, "nslimit1")))
  344. maxiter = scale_clamp(agnnodes(g), atof(s));
  345. for (size_t c = 0; c < GD_comp(g).size; c++) {
  346. GD_nlist(g) = GD_comp(g).list[c];
  347. rank(g, (GD_n_cluster(g) == 0 ? 1 : 0), maxiter); /* TB balance */
  348. }
  349. }
  350. /*
  351. * Assigns ranks of non-leader nodes.
  352. * Expands same, min, max rank sets.
  353. * Leaf sets and clusters remain merged.
  354. * Sets minrank and maxrank appropriately.
  355. */
  356. static void expand_ranksets(graph_t *g) {
  357. int c;
  358. node_t *n, *leader;
  359. if ((n = agfstnode(g))) {
  360. GD_minrank(g) = INT_MAX;
  361. GD_maxrank(g) = -1;
  362. while (n) {
  363. leader = UF_find(n);
  364. /* The following works because ND_rank(n) == 0 if n is not in a
  365. * cluster, and ND_rank(n) = the local rank offset if n is in
  366. * a cluster. */
  367. if (leader != n)
  368. ND_rank(n) += ND_rank(leader);
  369. if (GD_maxrank(g) < ND_rank(n))
  370. GD_maxrank(g) = ND_rank(n);
  371. if (GD_minrank(g) > ND_rank(n))
  372. GD_minrank(g) = ND_rank(n);
  373. if (ND_ranktype(n) && (ND_ranktype(n) != LEAFSET))
  374. UF_singleton(n);
  375. n = agnxtnode(g, n);
  376. }
  377. if (g == dot_root(g)) {
  378. if (CL_type == LOCAL) {
  379. for (c = 1; c <= GD_n_cluster(g); c++)
  380. set_minmax(GD_clust(g)[c]);
  381. } else {
  382. find_clusters(g);
  383. }
  384. }
  385. } else {
  386. GD_minrank(g) = GD_maxrank(g) = 0;
  387. }
  388. }
  389. static void dot1_rank(graph_t *g)
  390. {
  391. point p;
  392. edgelabel_ranks(g);
  393. collapse_sets(g,g);
  394. /*collapse_leaves(g); */
  395. class1(g);
  396. p = minmax_edges(g);
  397. decompose(g, 0);
  398. acyclic(g);
  399. if (minmax_edges2(g, p))
  400. decompose(g, 0);
  401. rank1(g);
  402. expand_ranksets(g);
  403. cleanup1(g);
  404. }
  405. void dot_rank(graph_t *g) {
  406. if (mapbool(agget(g, "newrank"))) {
  407. GD_flags(g) |= NEW_RANK;
  408. dot2_rank(g);
  409. }
  410. else
  411. dot1_rank(g);
  412. if (Verbose)
  413. fprintf (stderr, "Maxrank = %d, minrank = %d\n", GD_maxrank(g), GD_minrank(g));
  414. }
  415. bool is_cluster(graph_t * g)
  416. {
  417. return is_a_cluster(g); // from utils.c
  418. }
  419. /* new ranking code:
  420. * Allows more constraints
  421. * Copy of level.c in dotgen2
  422. * Many of the utility functions are simpler or gone with
  423. * cgraph library.
  424. */
  425. #define BACKWARD_PENALTY 1000
  426. #define STRONG_CLUSTER_WEIGHT 1000
  427. #define NORANK 6
  428. #define ROOT "\177root"
  429. #define TOPNODE "\177top"
  430. #define BOTNODE "\177bot"
  431. /* hops is not used in dot, so we overload it to
  432. * contain the index of the connected component
  433. */
  434. #define ND_comp(n) ND_hops(n)
  435. static void set_parent(graph_t* g, graph_t* p)
  436. {
  437. GD_parent(g) = p;
  438. make_new_cluster(p, g);
  439. node_induce(p, g);
  440. }
  441. static bool is_empty(graph_t *g) {
  442. return !agfstnode(g);
  443. }
  444. static bool is_a_strong_cluster(graph_t * g)
  445. {
  446. char *str = agget(g, "compact");
  447. return mapbool(str);
  448. }
  449. static int rankset_kind(graph_t * g)
  450. {
  451. char *str = agget(g, "rank");
  452. if (str && str[0]) {
  453. if (!strcmp(str, "min"))
  454. return MINRANK;
  455. if (!strcmp(str, "source"))
  456. return SOURCERANK;
  457. if (!strcmp(str, "max"))
  458. return MAXRANK;
  459. if (!strcmp(str, "sink"))
  460. return SINKRANK;
  461. if (!strcmp(str, "same"))
  462. return SAMERANK;
  463. }
  464. return NORANK;
  465. }
  466. static bool is_nonconstraint(edge_t * e)
  467. {
  468. char *constr;
  469. if (E_constr && (constr = agxget(e, E_constr))) {
  470. if (constr[0] && !mapbool(constr))
  471. return true;
  472. }
  473. return false;
  474. }
  475. static node_t *find(node_t * n)
  476. {
  477. node_t *set;
  478. if ((set = ND_set(n))) {
  479. if (set != n)
  480. set = ND_set(n) = find(set);
  481. } else
  482. set = ND_set(n) = n;
  483. return set;
  484. }
  485. static node_t *union_one(node_t * leader, node_t * n)
  486. {
  487. if (n)
  488. return (ND_set(find(n)) = find(leader));
  489. else
  490. return leader;
  491. }
  492. static node_t *union_all(graph_t * g)
  493. {
  494. node_t *n, *leader;
  495. n = agfstnode(g);
  496. if (!n)
  497. return n;
  498. leader = find(n);
  499. while ((n = agnxtnode(g, n)))
  500. union_one(leader, n);
  501. return leader;
  502. }
  503. static void compile_samerank(graph_t * ug, graph_t * parent_clust)
  504. {
  505. graph_t *s; /* subgraph being scanned */
  506. graph_t *clust; /* cluster that contains the rankset */
  507. node_t *n, *leader;
  508. if (is_empty(ug))
  509. return;
  510. if (is_a_cluster(ug)) {
  511. clust = ug;
  512. if (parent_clust) {
  513. GD_level(ug) = GD_level(parent_clust) + 1;
  514. set_parent(ug, parent_clust);
  515. }
  516. else
  517. GD_level(ug) = 0;
  518. } else
  519. clust = parent_clust;
  520. /* process subgraphs of this subgraph */
  521. for (s = agfstsubg(ug); s; s = agnxtsubg(s))
  522. compile_samerank(s, clust);
  523. /* process this subgraph as a cluster */
  524. if (is_a_cluster(ug)) {
  525. for (n = agfstnode(ug); n; n = agnxtnode(ug, n)) {
  526. if (ND_clust(n) == 0)
  527. ND_clust(n) = ug;
  528. #ifdef DEBUG
  529. fprintf(stderr, "(%s) %s %p\n", agnameof(ug), agnameof(n),
  530. ND_clust(n));
  531. #endif
  532. }
  533. }
  534. /* process this subgraph as a rankset */
  535. switch (rankset_kind(ug)) {
  536. case SOURCERANK: // fall through
  537. case MINRANK:
  538. leader = union_all(ug);
  539. if (clust != NULL) {
  540. GD_minrep(clust) = union_one(leader, GD_minrep(clust));
  541. }
  542. break;
  543. case SINKRANK: // fall through
  544. case MAXRANK:
  545. leader = union_all(ug);
  546. if (clust != NULL) {
  547. GD_maxrep(clust) = union_one(leader, GD_maxrep(clust));
  548. }
  549. break;
  550. case SAMERANK:
  551. leader = union_all(ug);
  552. /* do we need to record these ranksets? */
  553. break;
  554. case NORANK:
  555. break;
  556. default: /* unrecognized - warn and do nothing */
  557. agwarningf("%s has unrecognized rank=%s", agnameof(ug),
  558. agget(ug, "rank"));
  559. }
  560. /* a cluster may become degenerate */
  561. if (is_a_cluster(ug) && GD_minrep(ug)) {
  562. if (GD_minrep(ug) == GD_maxrep(ug)) {
  563. node_t *up = union_all(ug);
  564. GD_minrep(ug) = up;
  565. GD_maxrep(ug) = up;
  566. }
  567. }
  568. }
  569. static graph_t *dot_lca(graph_t * c0, graph_t * c1)
  570. {
  571. while (c0 != c1) {
  572. if (GD_level(c0) >= GD_level(c1))
  573. c0 = GD_parent(c0);
  574. else
  575. c1 = GD_parent(c1);
  576. }
  577. return c0;
  578. }
  579. static bool is_internal_to_cluster(edge_t * e)
  580. {
  581. graph_t *par, *ct, *ch;
  582. ct = ND_clust(agtail(e));
  583. ch = ND_clust(aghead(e));
  584. if (ct == ch)
  585. return true;
  586. par = dot_lca(ct, ch);
  587. if (par == ct || par == ch)
  588. return true;
  589. return false;
  590. }
  591. static node_t* Last_node;
  592. static node_t* makeXnode (graph_t* G, char* name)
  593. {
  594. node_t *n = agnode(G, name, 1);
  595. alloc_elist(4, ND_in(n));
  596. alloc_elist(4, ND_out(n));
  597. if (Last_node) {
  598. ND_prev(n) = Last_node;
  599. ND_next(Last_node) = n;
  600. } else {
  601. ND_prev(n) = NULL;
  602. GD_nlist(G) = n;
  603. }
  604. Last_node = n;
  605. ND_next(n) = NULL;
  606. return n;
  607. }
  608. static void compile_nodes(graph_t * g, graph_t * Xg)
  609. {
  610. /* build variables */
  611. node_t *n;
  612. Last_node = NULL;
  613. for (n = agfstnode(g); n; n = agnxtnode(g, n)) {
  614. if (find(n) == n)
  615. ND_rep(n) = makeXnode (Xg, agnameof(n));
  616. }
  617. for (n = agfstnode(g); n; n = agnxtnode(g, n)) {
  618. if (ND_rep(n) == 0)
  619. ND_rep(n) = ND_rep(find(n));
  620. }
  621. }
  622. static void merge(edge_t * e, int minlen, int weight)
  623. {
  624. ED_minlen(e) = MAX(ED_minlen(e), minlen);
  625. ED_weight(e) += weight;
  626. }
  627. static void strong(graph_t * g, node_t * t, node_t * h, edge_t * orig)
  628. {
  629. edge_t *e;
  630. if ((e = agfindedge(g, t, h)) ||
  631. (e = agfindedge(g, h, t)) || (e = agedge(g, t, h, 0, 1)))
  632. merge(e, ED_minlen(orig), ED_weight(orig));
  633. else
  634. agerrorf("ranking: failure to create strong constraint edge between nodes %s and %s\n",
  635. agnameof(t), agnameof(h));
  636. }
  637. static void weak(graph_t * g, node_t * t, node_t * h, edge_t * orig)
  638. {
  639. node_t *v;
  640. edge_t *e, *f;
  641. static int id;
  642. char buf[100];
  643. for (e = agfstin(g, t); e; e = agnxtin(g, e)) {
  644. /* merge with existing weak edge (e,f) */
  645. v = agtail(e);
  646. if ((f = agfstout(g, v)) && (aghead(f) == h)) {
  647. return;
  648. }
  649. }
  650. if (!e) {
  651. snprintf(buf, sizeof(buf), "_weak_%d", id++);
  652. v = makeXnode(g, buf);
  653. e = agedge(g, v, t, 0, 1);
  654. f = agedge(g, v, h, 0, 1);
  655. }
  656. ED_minlen(e) = MAX(ED_minlen(e), 0); /* effectively a nop */
  657. ED_weight(e) += ED_weight(orig) * BACKWARD_PENALTY;
  658. ED_minlen(f) = MAX(ED_minlen(f), ED_minlen(orig));
  659. ED_weight(f) += ED_weight(orig);
  660. }
  661. static void compile_edges(graph_t * ug, graph_t * Xg)
  662. {
  663. node_t *n;
  664. edge_t *e;
  665. node_t *Xt, *Xh;
  666. graph_t *tc, *hc;
  667. /* build edge constraints */
  668. for (n = agfstnode(ug); n; n = agnxtnode(ug, n)) {
  669. Xt = ND_rep(n);
  670. for (e = agfstout(ug, n); e; e = agnxtout(ug, e)) {
  671. if (is_nonconstraint(e))
  672. continue;
  673. Xh = ND_rep(find(aghead(e)));
  674. if (Xt == Xh)
  675. continue;
  676. tc = ND_clust(agtail(e));
  677. hc = ND_clust(aghead(e));
  678. if (is_internal_to_cluster(e)) {
  679. graph_t *clust_tail = ND_clust(agtail(e));
  680. graph_t *clust_head = ND_clust(aghead(e));
  681. /* determine if graph requires reversed edge */
  682. if ((clust_tail != NULL && find(agtail(e)) == GD_maxrep(clust_tail))
  683. || (clust_head != NULL && find(aghead(e)) == GD_minrep(clust_head))) {
  684. node_t *temp = Xt;
  685. Xt = Xh;
  686. Xh = temp;
  687. }
  688. strong(Xg, Xt, Xh, e);
  689. } else {
  690. if (is_a_strong_cluster(tc) || is_a_strong_cluster(hc))
  691. weak(Xg, Xt, Xh, e);
  692. else
  693. strong(Xg, Xt, Xh, e);
  694. }
  695. }
  696. }
  697. }
  698. static void compile_clusters(graph_t* g, graph_t* Xg, node_t* top, node_t* bot)
  699. {
  700. node_t *n;
  701. node_t *rep;
  702. edge_t *e;
  703. graph_t *sub;
  704. if (is_a_cluster(g) && is_a_strong_cluster(g)) {
  705. for (n = agfstnode(g); n; n = agnxtnode(g, n)) {
  706. if (agfstin(g, n) == 0) {
  707. rep = ND_rep(find(n));
  708. if (!top) top = makeXnode(Xg,TOPNODE);
  709. agedge(Xg, top, rep, 0, 1);
  710. }
  711. if (agfstout(g, n) == 0) {
  712. rep = ND_rep(find(n));
  713. if (!bot) bot = makeXnode(Xg,BOTNODE);
  714. agedge(Xg, rep, bot, 0, 1);
  715. }
  716. }
  717. if (top && bot) {
  718. e = agedge(Xg, top, bot, 0, 1);
  719. merge(e, 0, STRONG_CLUSTER_WEIGHT);
  720. }
  721. }
  722. for (sub = agfstsubg(g); sub; sub = agnxtsubg(sub))
  723. compile_clusters(sub, Xg, top, bot);
  724. }
  725. static void reverse_edge2(graph_t * g, edge_t * e)
  726. {
  727. edge_t *rev;
  728. rev = agfindedge(g, aghead(e), agtail(e));
  729. if (!rev)
  730. rev = agedge(g, aghead(e), agtail(e), 0, 1);
  731. merge(rev, ED_minlen(e), ED_weight(e));
  732. agdelete(g, e);
  733. }
  734. static void dfs(graph_t * g, node_t * v)
  735. {
  736. edge_t *e, *f;
  737. node_t *w;
  738. if (ND_mark(v))
  739. return;
  740. ND_mark(v) = true;
  741. ND_onstack(v) = true;
  742. for (e = agfstout(g, v); e; e = f) {
  743. f = agnxtout(g, e);
  744. w = aghead(e);
  745. if (ND_onstack(w))
  746. reverse_edge2(g, e);
  747. else {
  748. if (!ND_mark(w))
  749. dfs(g, w);
  750. }
  751. }
  752. ND_onstack(v) = false;
  753. }
  754. static void break_cycles(graph_t * g)
  755. {
  756. node_t *n;
  757. for (n = agfstnode(g); n; n = agnxtnode(g, n)) {
  758. ND_mark(n) = false;
  759. ND_onstack(n) = false;
  760. }
  761. for (n = agfstnode(g); n; n = agnxtnode(g, n))
  762. dfs(g, n);
  763. }
  764. /* setMinMax:
  765. * This will only be called with the root graph or a cluster
  766. * which are guaranteed to contain nodes. Thus, leader will be
  767. * set.
  768. */
  769. static void setMinMax (graph_t* g, int doRoot)
  770. {
  771. int c, v;
  772. node_t *n;
  773. node_t* leader = NULL;
  774. /* Do child clusters */
  775. for (c = 1; c <= GD_n_cluster(g); c++)
  776. setMinMax(GD_clust(g)[c], 0);
  777. if (!GD_parent(g) && !doRoot) // root graph
  778. return;
  779. GD_minrank(g) = INT_MAX;
  780. GD_maxrank(g) = -1;
  781. for (n = agfstnode(g); n; n = agnxtnode(g, n)) {
  782. v = ND_rank(n);
  783. if (GD_maxrank(g) < v)
  784. GD_maxrank(g) = v;
  785. if (GD_minrank(g) > v) {
  786. GD_minrank(g) = v;
  787. leader = n;
  788. }
  789. }
  790. GD_leader(g) = leader;
  791. }
  792. /* readout_levels:
  793. * Store node rank information in original graph.
  794. * Set rank bounds in graph and clusters
  795. * Free added data structures.
  796. *
  797. * rank2 is called with balance=1, which ensures that minrank=0
  798. */
  799. static void readout_levels(graph_t * g, graph_t * Xg, int ncc)
  800. {
  801. node_t *n;
  802. node_t *xn;
  803. int* minrk = NULL;
  804. int doRoot = 0;
  805. GD_minrank(g) = INT_MAX;
  806. GD_maxrank(g) = -1;
  807. if (ncc > 1) {
  808. int i;
  809. minrk = gv_calloc(ncc + 1, sizeof(int));
  810. for (i = 1; i <= ncc; i++)
  811. minrk[i] = INT_MAX;
  812. }
  813. for (n = agfstnode(g); n; n = agnxtnode(g, n)) {
  814. xn = ND_rep(find(n));
  815. ND_rank(n) = ND_rank(xn);
  816. if (GD_maxrank(g) < ND_rank(n))
  817. GD_maxrank(g) = ND_rank(n);
  818. if (GD_minrank(g) > ND_rank(n))
  819. GD_minrank(g) = ND_rank(n);
  820. if (minrk) {
  821. ND_comp(n) = ND_comp(xn);
  822. minrk[ND_comp(n)] = MIN(minrk[ND_comp(n)],ND_rank(n));
  823. }
  824. }
  825. if (minrk) {
  826. for (n = agfstnode(g); n; n = agnxtnode(g, n))
  827. ND_rank(n) -= minrk[ND_comp(n)];
  828. /* Non-uniform shifting, so recompute maxrank/minrank of root graph */
  829. doRoot = 1;
  830. }
  831. else if (GD_minrank(g) > 0) { /* should never happen */
  832. int delta = GD_minrank(g);
  833. for (n = agfstnode(g); n; n = agnxtnode(g, n))
  834. ND_rank(n) -= delta;
  835. GD_minrank(g) -= delta;
  836. GD_maxrank(g) -= delta;
  837. }
  838. setMinMax(g, doRoot);
  839. /* release fastgraph memory from Xg */
  840. for (n = agfstnode(Xg); n; n = agnxtnode(Xg, n)) {
  841. free_list(ND_in(n));
  842. free_list(ND_out(n));
  843. }
  844. free(ND_alg(agfstnode(g)));
  845. for (n = agfstnode(g); n; n = agnxtnode(g, n)) {
  846. ND_alg(n) = NULL;
  847. }
  848. free(minrk);
  849. }
  850. static void dfscc(graph_t * g, node_t * n, int cc)
  851. {
  852. edge_t *e;
  853. if (ND_comp(n) == 0) {
  854. ND_comp(n) = cc;
  855. for (e = agfstout(g, n); e; e = agnxtout(g, e))
  856. dfscc(g, aghead(e), cc);
  857. for (e = agfstin(g, n); e; e = agnxtin(g, e))
  858. dfscc(g, agtail(e), cc);
  859. }
  860. }
  861. static int connect_components(graph_t * g)
  862. {
  863. int cc = 0;
  864. node_t *n;
  865. for (n = agfstnode(g); n; n = agnxtnode(g, n))
  866. ND_comp(n) = 0;
  867. for (n = agfstnode(g); n; n = agnxtnode(g, n))
  868. if (ND_comp(n) == 0)
  869. dfscc(g, n, ++cc);
  870. if (cc > 1) {
  871. node_t *root = makeXnode(g, ROOT);
  872. int ncc = 1;
  873. for (n = agfstnode(g); n; n = agnxtnode(g, n)) {
  874. if (ND_comp(n) == ncc) {
  875. (void) agedge(g, root, n, 0, 1);
  876. ncc++;
  877. }
  878. }
  879. }
  880. return (cc);
  881. }
  882. static void add_fast_edges (graph_t * g)
  883. {
  884. node_t *n;
  885. edge_t *e;
  886. for (n = agfstnode(g); n; n = agnxtnode(g, n)) {
  887. for (e = agfstout(g, n); e; e = agnxtout(g, e)) {
  888. elist_append(e, ND_out(n));
  889. elist_append(e, ND_in(aghead(e)));
  890. }
  891. }
  892. }
  893. static void my_init_graph(Agraph_t *g, Agobj_t *graph, void *arg)
  894. { int *sz = arg; (void)g; agbindrec(graph,"level graph rec",sz[0],true); }
  895. static void my_init_node(Agraph_t *g, Agobj_t *node, void *arg)
  896. { int *sz = arg; (void)g; agbindrec(node,"level node rec",sz[1],true); }
  897. static void my_init_edge(Agraph_t *g, Agobj_t *edge, void *arg)
  898. { int *sz = arg; (void)g; agbindrec(edge,"level edge rec",sz[2],true); }
  899. static Agcbdisc_t mydisc = { {my_init_graph,0,0}, {my_init_node,0,0}, {my_init_edge,0,0} };
  900. int infosizes[] = {
  901. sizeof(Agraphinfo_t),
  902. sizeof(Agnodeinfo_t),
  903. sizeof(Agedgeinfo_t)
  904. };
  905. void dot2_rank(graph_t *g) {
  906. int ssize;
  907. int ncc, maxiter = INT_MAX;
  908. char *s;
  909. graph_t *Xg;
  910. Last_node = NULL;
  911. Xg = agopen("level assignment constraints", Agstrictdirected, 0);
  912. agbindrec(Xg,"level graph rec",sizeof(Agraphinfo_t),true);
  913. agpushdisc(Xg,&mydisc,infosizes);
  914. edgelabel_ranks(g);
  915. if ((s = agget(g, "nslimit1")))
  916. maxiter = scale_clamp(agnnodes(g), atof(s));
  917. else
  918. maxiter = INT_MAX;
  919. compile_samerank(g, 0);
  920. compile_nodes(g, Xg);
  921. compile_edges(g, Xg);
  922. compile_clusters(g, Xg, 0, 0);
  923. break_cycles(Xg);
  924. ncc = connect_components(Xg);
  925. add_fast_edges (Xg);
  926. if ((s = agget(g, "searchsize")))
  927. ssize = atoi(s);
  928. else
  929. ssize = -1;
  930. rank2(Xg, 1, maxiter, ssize);
  931. /* fastgr(Xg); */
  932. readout_levels(g, Xg, ncc);
  933. #ifdef DEBUG
  934. fprintf (stderr, "Xg %d nodes %d edges\n", agnnodes(Xg), agnedges(Xg));
  935. #endif
  936. agclose(Xg);
  937. }