sugi4.c 23 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030
  1. /*
  2. * Copyright 2021
  3. *
  4. * This program is free software: you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License as published by
  6. * the Free Software Foundation, either version 3 of the License, or
  7. * (at your option) any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License
  15. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  16. *
  17. * These are the four essential freedoms with GNU GPL software:
  18. * 1: freedom to run the program, for any purpose
  19. * 2: freedom to study how the program works, and change it to make it do what you wish
  20. * 3: freedom to redistribute copies to help your Free Software friends
  21. * 4: freedom to distribute copies of your modified versions to your Free Software friends
  22. * , ,
  23. * / \
  24. * ((__-^^-,-^^-__))
  25. * `-_---' `---_-'
  26. * `--|o` 'o|--'
  27. * \ ` /
  28. * ): :(
  29. * :o_o:
  30. * "-"
  31. *
  32. * SPDX-License-Identifier: GPL-3.0+
  33. * License-Filename: LICENSE
  34. */
  35. #include "config.h"
  36. #include <stdio.h>
  37. #include <stdlib.h>
  38. #include <string.h>
  39. #include <math.h> /* for fabs() */
  40. #include "main.h"
  41. #include "hier.h"
  42. #include "uniqnode.h"
  43. #include "sugi.h"
  44. #include "dpmem.h"
  45. /* how much double values may differ when seen as same */
  46. #define LOWVAL (0.1)
  47. struct suginode {
  48. int id; /* uniq node number */
  49. int level; /* rel. y level */
  50. int pos; /* rel. x position */
  51. int *outgoing; /* outgoing edges */
  52. int outdegree; /* number of outgoing edges */
  53. int *incoming; /* incoming edges */
  54. int indegree; /* number of incoming edges */
  55. double barydown; /* barycenter value */
  56. double baryup; /* barycenter value */
  57. int qsortpos; /* position for stable qsort() */
  58. };
  59. /* set to 1 for debug output */
  60. static int s3debug = 0;
  61. /* max level in use */
  62. static int gmaxlevel = 0;
  63. /* number of levels */
  64. static int gnlevels = 0;
  65. /* node data arrays */
  66. static struct suginode **sugidata = NULL;
  67. /* nodes at level */
  68. static struct gml_nlist **glevelnodes = NULL;
  69. static struct gml_nlist **glevelnodesend = NULL;
  70. /* number of nodes at level */
  71. static int *nglevelnodes = NULL;
  72. /* bool set if going downwards from level n+1 to level n, else upwards */
  73. static int down = 0;
  74. /* cur. crossings */
  75. static int curcross = 0;
  76. /* how many nodes at level */
  77. static int levellength(int level)
  78. {
  79. if (level < 0) {
  80. printf("%s(): level %d is out of range\n", __func__, level);
  81. fflush(stdout);
  82. return (0);
  83. }
  84. if (level > gmaxlevel) {
  85. printf("%s(): level %d is out of range\n", __func__, level);
  86. fflush(stdout);
  87. return (0);
  88. }
  89. return (nglevelnodes[level]);
  90. }
  91. /* renumber pos field of nodes at one level */
  92. static void renumber(struct suginode *a)
  93. {
  94. int i = 0;
  95. for (i = 0; i < levellength(a[0].level); i++) {
  96. (a + i)->pos = i; /* a[i].pos */
  97. }
  98. return;
  99. }
  100. /* return 0 if graph has no crossings */
  101. static int check0(struct gml_graph *g)
  102. {
  103. int sum = 0;
  104. int i = 0;
  105. for (i = 0; i < gnlevels; i++) {
  106. /* add number of crossings at level i */
  107. sum += g->numce[i];
  108. }
  109. return (sum);
  110. }
  111. /* get pos. of node with nr in array b with nodes */
  112. static int posat(struct suginode *b, int nr)
  113. {
  114. int ret = 0;
  115. int i = 0;
  116. /* check all nodes in b */
  117. for (i = 0; i < levellength(b[0].level); i++) {
  118. if (i != b[i].pos) {
  119. printf("%s(): at level %d pos %d but found pos %d\n", __func__, b[0].level, i, b[i].pos);
  120. }
  121. if (b[i].id == nr) {
  122. break;
  123. }
  124. }
  125. /* check this is the found node and get position */
  126. if (b[i].id == nr) {
  127. ret = b[i].pos;
  128. } else {
  129. /* shouldnothappen */
  130. printf("%s(): node %d not found at level %d\n", __func__, nr, b[0].level);
  131. fflush(stdout);
  132. ret = -1;
  133. }
  134. return (ret);
  135. }
  136. /* median value of one node */
  137. static void medianvalue(struct suginode *a, struct suginode *b)
  138. {
  139. int *lookat = NULL;
  140. int nlookat = 0;
  141. int i = 0;
  142. int nn = 0;
  143. int p = 0;
  144. double val = 0.0;
  145. if (down) {
  146. /* look at outgoing edges */
  147. lookat = a->outgoing;
  148. nlookat = a->outdegree;
  149. } else {
  150. /* look at incoming edges */
  151. lookat = a->incoming;
  152. nlookat = a->indegree;
  153. a->baryup = 1.0;
  154. }
  155. /* if no degree, place node most left */
  156. if (nlookat == 0) {
  157. if (down) {
  158. a->barydown = (-1.0);
  159. } else {
  160. a->baryup = (-1.0);
  161. }
  162. return;
  163. }
  164. /* for every degree */
  165. for (i = 0; i < nlookat; i++) {
  166. /* get number of connecting node */
  167. nn = lookat[i];
  168. /* get pos. of connecting node in edge */
  169. p = posat(b, nn);
  170. /* sum positions */
  171. val = (val + (double)p);
  172. }
  173. /* mult, to get better resoultion */
  174. val = (val * 100);
  175. /* avg., div. by degree */
  176. val = (val / (double)nlookat);
  177. if (down) {
  178. a->barydown = (val);
  179. } else {
  180. a->baryup = (val);
  181. }
  182. return;
  183. }
  184. /* compare bary values */
  185. static int comparevalue(const void *a, const void *b)
  186. {
  187. struct suginode *x = (struct suginode *)a;
  188. struct suginode *y = (struct suginode *)b;
  189. double baryx = 0.0;
  190. double baryy = 0.0;
  191. if (down) {
  192. baryx = x->barydown;
  193. baryy = y->barydown;
  194. } else {
  195. baryx = x->baryup;
  196. baryy = y->baryup;
  197. }
  198. /* if (baryx == baryy) */
  199. if (fabs(baryx - baryy) <= LOWVAL) {
  200. /* for stable qsort() use pos field at equal */
  201. return (y->qsortpos - x->qsortpos);
  202. }
  203. if (baryx > baryy) {
  204. return (1);
  205. }
  206. /* baryx < baryy */
  207. return (-1);
  208. }
  209. /* */
  210. static int twovertcross(struct suginode *a, struct suginode *b, struct suginode *cc)
  211. {
  212. int i = 0;
  213. int j = 0;
  214. int sum = 0;
  215. int c = 0;
  216. int d = 0;
  217. if (s3debug || 0) {
  218. printf("node %d level %d has %d children, node %d level %d has %d children\n", a->id, a->level, a->outdegree, b->id,
  219. b->level, b->outdegree);
  220. }
  221. if (a->outdegree == 0) {
  222. return (0);
  223. }
  224. if (b->outdegree == 0) {
  225. return (0);
  226. }
  227. for (i = 0; i < a->outdegree; i++) {
  228. for (j = 0; j < b->outdegree; j++) {
  229. /* get pos of outgoing nodes */
  230. c = posat(cc, a->outgoing[i]);
  231. d = posat(cc, b->outgoing[j]);
  232. if (c > d) {
  233. sum++;
  234. }
  235. }
  236. }
  237. return (sum);
  238. }
  239. /* */
  240. static int levelcross(struct suginode *a, struct suginode *b)
  241. {
  242. int cross = 0;
  243. int i = 0;
  244. int j = 0;
  245. int t = 0;
  246. if (s3debug || 0) {
  247. printf("%s(): down=%d level-a=%d level-b=%d\n", __func__, down, a[0].level, b[0].level);
  248. }
  249. if (down) {
  250. /* down==1 */
  251. i = levellength(b[0].level);
  252. t = levellength(a[0].level);
  253. if (i == 0 || t == 0) {
  254. /*shouldnothappen */
  255. return (0);
  256. }
  257. for (i = 0; i < t - 1; i++) {
  258. for (j = i + 1; j < t; j++) {
  259. cross = cross + twovertcross((a + i), (a + j), b);
  260. }
  261. }
  262. } else {
  263. /* down==0 */
  264. i = levellength(a[0].level);
  265. t = levellength(b[0].level);
  266. if (i == 0 || t == 0) {
  267. /*shouldnothappen */
  268. return (0);
  269. }
  270. for (i = 0; i < (t - 1); i++) {
  271. for (j = (i + 1); j < t; j++) {
  272. cross = cross + twovertcross((b + i), (b + j), a);
  273. }
  274. }
  275. }
  276. return (cross);
  277. }
  278. /* check eq bary values in t nodes at this level */
  279. static int equals(struct suginode *a, int t)
  280. {
  281. int res = 0;
  282. int i = 0;
  283. struct suginode *temp = NULL;
  284. double baryx = 0.0;
  285. double baryy = 0.0;
  286. temp = dp_calloc(1, sizeof(struct suginode));
  287. /* scan all nodes at this level */
  288. for (i = 0; i < (t - 1); i++) {
  289. if (down) {
  290. baryx = (a + i)->barydown;
  291. baryy = (a + i + 1)->barydown;
  292. } else {
  293. baryx = (a + i)->baryup;
  294. baryy = (a + i + 1)->baryup;
  295. }
  296. /* if (baryx == baryy) swap nodes */
  297. if (fabs(baryx - baryy) <= LOWVAL) {
  298. /* copy node in (a+i) to temp */
  299. memcpy(temp, a + i, sizeof(struct suginode));
  300. /* copy node in (a+i+1) to (a+i) */
  301. memcpy(a + i, a + i + 1, sizeof(struct suginode));
  302. /* copy node in temp to (a+i+1) */
  303. memcpy(a + i + 1, temp, sizeof(struct suginode));
  304. /* indicate that changes were made */
  305. res++;
  306. }
  307. }
  308. temp = dp_free(temp);
  309. if (temp) {
  310. }
  311. /* return 0 if no changes made, <>0 if changed */
  312. return (res);
  313. }
  314. /* sort between level a and level b
  315. * if going up from level 1 to n, a=level-1, b=level-0
  316. */
  317. static void mediansort(struct gml_graph *g, struct suginode *a, struct suginode *b)
  318. {
  319. int nc = 0;
  320. int t = 0;
  321. int tb = 0;
  322. int i = 0;
  323. int p = 0;
  324. int la = 0;
  325. int ld = 0;
  326. struct suginode *dummy = NULL;
  327. if (a == NULL) { /*shouldnothappen */
  328. return;
  329. }
  330. if (b == NULL) { /*shouldnothappen */
  331. return;
  332. }
  333. if (a[0].level == b[0].level) {
  334. printf("%s(): a %p and b %p have same level %d out of range\n", __func__, (void *)a, (void *)b, a[0].level);
  335. fflush(stdout);
  336. return;
  337. }
  338. if (a[0].level < 0 || a[0].level > gmaxlevel) {
  339. printf("%s(): level-a %d out of range 0...%d\n", __func__, a[0].level, gmaxlevel);
  340. fflush(stdout);
  341. return;
  342. }
  343. if (b[0].level < 0 || b[0].level > gmaxlevel) {
  344. printf("%s(): level-b %d out of range 0...%d\n", __func__, b[0].level, gmaxlevel);
  345. fflush(stdout);
  346. return;
  347. }
  348. /* how many nodes at level of a */
  349. t = levellength(a[0].level);
  350. if (t == 0) {
  351. printf("%s(): a-level 0 nodes at level %d\n", __func__, a[0].level);
  352. return;
  353. }
  354. /* only 1 node at this level then no crossings */
  355. if (t == 1) {
  356. return;
  357. }
  358. /* how many nodes at level of b */
  359. tb = levellength(b[0].level);
  360. if (tb == 0) {
  361. printf("%s(): b-level 0 nodes at level %d\n", __func__, b[0].level);
  362. return;
  363. }
  364. /* a-level is 1, b-level is 0, at [1...gmaxlevel] down=0; */
  365. /* a-level is (gmaxlevel - 1), b-level is (gmaxlevel - 2) at [.gmaxlevel...1] */
  366. if (a[0].level >= b[0].level) {
  367. down = 0;
  368. } else {
  369. down = 1;
  370. }
  371. if (s3debug || 0) {
  372. printf("%s(): level-a=%d has %d nodes, level-b=%d has %d nodes, down=%d\n", __func__, a[0].level, t, b[0].level, tb, down);
  373. }
  374. /* buffer for test result */
  375. dummy = dp_calloc(1, (t * sizeof(struct suginode)));
  376. /* calc node median of every node at level a */
  377. for (i = 0; i < t; i++) {
  378. /* get i'th node in array a and search in array b */
  379. medianvalue((a + i), b);
  380. if (s3debug || 0) {
  381. /* print node bary value */
  382. if (down) {
  383. printf("%s(): barydown=%f node %d\n", __func__, a[i].barydown, a[i].id);
  384. } else {
  385. printf("%s(): baryup=%f node %d\n", __func__, a[i].baryup, a[i].id);
  386. }
  387. }
  388. }
  389. /* copy a to dummy as backup */
  390. (void)memcpy(dummy, sugidata[a[0].level], (t * sizeof(struct suginode)));
  391. if (s3debug || 0) {
  392. printf("%s(): sorting %d nmemb\n", __func__, t);
  393. }
  394. /* sort on barycenter value if more then 1 member */
  395. if (t > 1) {
  396. /* for stable qsort() set pos field */
  397. for (i = 0; i < t; i++) {
  398. sugidata[a[0].level]->qsortpos = i;
  399. }
  400. /* sort on avg. in/out positions of connecting nodes */
  401. qsort(sugidata[a[0].level], t, sizeof(struct suginode), comparevalue);
  402. /* nodes may have changed positions, re-number the pos field */
  403. renumber(a);
  404. }
  405. la = levelcross(a, b);
  406. renumber(dummy);
  407. ld = levelcross(dummy, b);
  408. if (s3debug || 0) {
  409. printf("%s(): crossings level-a=%d is %d versus %d in dummy\n", __func__, a[0].level, la, ld);
  410. }
  411. /* save this crossing count */
  412. g->numce[a[0].level] = la;
  413. if (la == 0) {
  414. dummy = dp_free(dummy);
  415. if (dummy) {
  416. }
  417. return;
  418. }
  419. /* if crossings in a > in dummy, use dummy backup */
  420. if (la > ld) {
  421. /* dummy backup is better: less crossings */
  422. /* copy dummy to a */
  423. memcpy(sugidata[a[0].level], dummy, (t * sizeof(struct suginode)));
  424. renumber(a);
  425. /* save this crossing count */
  426. g->numce[a[0].level] = ld;
  427. if (ld == 0) {
  428. dummy = dp_free(dummy);
  429. if (dummy) {
  430. }
  431. return;
  432. }
  433. }
  434. /* now swap nodes with equal bary at this level */
  435. for (p = 0; p < 5; p++) {
  436. /* copy a to dummy as backup */
  437. memcpy(dummy, sugidata[a[0].level], (t * sizeof(struct suginode)));
  438. /* swap nodes with same barycenter and return number of nodes swapped */
  439. nc = equals(sugidata[a[0].level], t);
  440. if (nc == 0) {
  441. /* no changes made to node positions in this level */
  442. break;
  443. }
  444. /* changes were made, so re-number node pos */
  445. renumber(a);
  446. la = levelcross(a, b);
  447. if (la == 0) {
  448. /* save this crossing count */
  449. g->numce[a[0].level] = la;
  450. break;
  451. }
  452. ld = levelcross(dummy, b);
  453. /* save this crossing count */
  454. g->numce[a[0].level] = la;
  455. if (la >= ld) {
  456. /* dummy backup has less crossings, continue with dummy */
  457. /* copy dummy to a */
  458. memcpy(sugidata[a[0].level], dummy, (t * sizeof(struct suginode)));
  459. renumber(a);
  460. /* save this crossing count */
  461. g->numce[a[0].level] = ld;
  462. if (ld == 0) {
  463. break;
  464. }
  465. }
  466. }
  467. dummy = dp_free(dummy);
  468. if (dummy) {
  469. }
  470. return;
  471. }
  472. /* create lists of nodes per level */
  473. static void cp_make_levelnodes(struct gml_graph *g)
  474. {
  475. struct gml_nlist *lnll = NULL;
  476. struct gml_nlist *newl = NULL;
  477. int i = 0;
  478. glevelnodes = dp_calloc(1, (gnlevels * sizeof(struct gml_nlist *)));
  479. glevelnodesend = dp_calloc(1, (gnlevels * sizeof(struct gml_nlist *)));
  480. nglevelnodes = dp_calloc(1, (gnlevels * sizeof(int)));
  481. lnll = g->nodelist;
  482. while (lnll) {
  483. /* rel. y level set by dfs/bfs */
  484. i = lnll->node->rely;
  485. newl = dp_calloc(1, sizeof(struct gml_nlist));
  486. newl->node = lnll->node;
  487. if (glevelnodes[i] == NULL) {
  488. glevelnodes[i] = newl;
  489. glevelnodesend[i] = newl;
  490. } else {
  491. glevelnodesend[i]->next = newl;
  492. glevelnodesend[i] = newl;
  493. }
  494. /* number of nodes at this level */
  495. nglevelnodes[i]++;
  496. lnll = lnll->next;
  497. }
  498. /* extra check */
  499. for (i = 0; i < gnlevels; i++) {
  500. if (nglevelnodes[i] == 0) {
  501. /* shouldnothappen */
  502. printf("%s(): level %d has no nodes\n", __func__, i);
  503. fflush(stdout);
  504. }
  505. }
  506. return;
  507. }
  508. /* clear nodes at level */
  509. static void clr_levelnodes(struct gml_graph *g)
  510. {
  511. struct gml_nlist *lnll = NULL;
  512. struct gml_nlist *nlnext = NULL;
  513. int i = 0;
  514. if (g) {
  515. }
  516. if (glevelnodes == NULL) {
  517. return;
  518. }
  519. for (i = 0; i < gnlevels; i++) {
  520. /* lists per pos. */
  521. lnll = glevelnodes[i];
  522. while (lnll) {
  523. nlnext = lnll->next;
  524. lnll = dp_free(lnll);
  525. if (lnll) {
  526. }
  527. lnll = nlnext;
  528. }
  529. glevelnodes[i] = NULL;
  530. glevelnodesend[i] = NULL;
  531. }
  532. glevelnodes = dp_free(glevelnodes);
  533. if (glevelnodes) {
  534. }
  535. glevelnodesend = dp_free(glevelnodesend);
  536. if (glevelnodesend) {
  537. }
  538. return;
  539. }
  540. /* clear number of nodes for every level */
  541. static void clr_nglevelnodes(void)
  542. {
  543. nglevelnodes = dp_free(nglevelnodes);
  544. if (nglevelnodes) {
  545. }
  546. return;
  547. }
  548. /* copy data into tree data */
  549. static void cp_data(struct gml_graph *g)
  550. {
  551. struct gml_elist *el = NULL;
  552. struct gml_nlist *lnll = NULL;
  553. int i = 0;
  554. int count = 0;
  555. int k = 0;
  556. sugidata = dp_calloc(1, (gnlevels * sizeof(struct suginode *)));
  557. /* create nodes on level */
  558. cp_make_levelnodes(g);
  559. for (i = 0; i < gnlevels; i++) {
  560. if (s3debug) {
  561. printf("%s(): level %d has %d nodes\n", __func__, i, nglevelnodes[i]);
  562. }
  563. sugidata[i] = dp_calloc(1, (nglevelnodes[i] * sizeof(struct suginode)));
  564. sugidata[i][0].level = i;
  565. /* get list of nodes at level i */
  566. lnll = glevelnodes[i];
  567. count = 0;
  568. while (lnll) {
  569. /* set node uniq number starting at 1 */
  570. sugidata[i][count].id = lnll->node->nr;
  571. sugidata[i][count].level = lnll->node->rely;
  572. sugidata[i][count].pos = count;
  573. if (s3debug) {
  574. printf("%s(): node %d has %d parents, %d children\n", __func__, lnll->node->nr,
  575. lnll->node->indegree, lnll->node->outdegree);
  576. }
  577. /* set incoming edges if any */
  578. sugidata[i][count].indegree = 0;
  579. sugidata[i][count].incoming = NULL;
  580. if (lnll->node->indegree > 0) {
  581. /* count numnber of edges without hor. edges */
  582. k = 0;
  583. el = lnll->node->incoming_e;
  584. while (el) {
  585. /* skip the hor. edges */
  586. if (el->edge->hedge == 0) {
  587. k++;
  588. }
  589. el = el->next;
  590. }
  591. sugidata[i][count].indegree = k; /* old lnll->node->indegree; */
  592. if (k > 0) {
  593. sugidata[i][count].incoming = dp_calloc(1, ( /* old: lnll->node->indegree */ k * sizeof(int)));
  594. /* */
  595. k = 0;
  596. el = lnll->node->incoming_e;
  597. while (el) {
  598. /* skip the hor. edges */
  599. if (el->edge->hedge == 0) {
  600. /* set number of to node */
  601. sugidata[i][count].incoming[k] = el->edge->from_node->nr;
  602. if (el->edge->to_node->nr != lnll->node->nr) {
  603. printf("%s(): fixme(1)\n", __func__);
  604. }
  605. k++;
  606. }
  607. el = el->next;
  608. }
  609. }
  610. }
  611. sugidata[i][count].outdegree = 0;
  612. sugidata[i][count].outgoing = NULL;
  613. /* set outgoing edges if any */
  614. if (lnll->node->outdegree > 0) {
  615. /* count numnber of edges without hor. edges */
  616. k = 0;
  617. el = lnll->node->outgoing_e;
  618. while (el) {
  619. /* skip hor. edges */
  620. if (el->edge->hedge == 0) {
  621. k++;
  622. }
  623. el = el->next;
  624. }
  625. /* set */
  626. if (k > 0) {
  627. sugidata[i][count].outdegree = k; /* old: lnll->node->outdegree; */
  628. sugidata[i][count].outgoing = dp_calloc(1, ( /* old: lnll->node->outdegree */ k * sizeof(int)));
  629. /* */
  630. k = 0;
  631. el = lnll->node->outgoing_e;
  632. while (el) {
  633. /* skip hor. edges */
  634. if (el->edge->hedge == 0) {
  635. /* set number of from node */
  636. sugidata[i][count].outgoing[k] = el->edge->to_node->nr;
  637. if (el->edge->from_node->nr != lnll->node->nr) {
  638. printf("%s(): fixme(2)\n", __func__);
  639. }
  640. k++;
  641. }
  642. el = el->next;
  643. }
  644. }
  645. }
  646. /*
  647. * to next x position
  648. */
  649. count++;
  650. /* to next node */
  651. lnll = lnll->next;
  652. }
  653. } /* to next level */
  654. if (s3debug || 0) {
  655. printf("%s(): sugidata[i][0].level values are ", __func__);
  656. for (i = 0; i < gnlevels; i++) {
  657. printf("%d ", sugidata[i][0].level);
  658. }
  659. printf("\n");
  660. }
  661. clr_levelnodes(g);
  662. return;
  663. }
  664. /* clear data in tree data */
  665. static void clr_data(struct gml_graph *g)
  666. {
  667. int i = 0;
  668. int j = 0;
  669. if (g) {
  670. }
  671. /* copy new node positions */
  672. for (i = 0; i < gnlevels; i++) {
  673. /* scan nodes at level [i] */
  674. if (sugidata[i]) {
  675. for (j = 0; j < nglevelnodes[i]; j++) {
  676. /* extra integrity check */
  677. if (sugidata[i][j].outgoing) {
  678. if (sugidata[i][j].outdegree == 0) {
  679. printf("%s(): sugidata[i][j].outgoing at zero outdegree\n", __func__);
  680. }
  681. }
  682. if (sugidata[i][j].outdegree || sugidata[i][j].outgoing) {
  683. sugidata[i][j].outgoing = dp_free(sugidata[i][j].outgoing);
  684. if (sugidata[i][j].outgoing) {
  685. }
  686. }
  687. if (sugidata[i][j].incoming != NULL) {
  688. if (sugidata[i][j].indegree == 0) {
  689. printf("%s(): sugidata[i][j].incoming with zero indegree\n", __func__);
  690. }
  691. }
  692. if (sugidata[i][j].indegree || sugidata[i][j].incoming) {
  693. sugidata[i][j].incoming = dp_free(sugidata[i][j].incoming);
  694. if (sugidata[i][j].incoming) {
  695. }
  696. }
  697. if (sugidata[i]) {
  698. }
  699. }
  700. sugidata[i] = dp_free(sugidata[i]);
  701. }
  702. }
  703. sugidata = dp_free(sugidata);
  704. if (sugidata) {
  705. }
  706. /* clear number of nodes at level */
  707. clr_nglevelnodes();
  708. return;
  709. }
  710. /* start */
  711. static void barycenter_4(struct gml_graph *g, int it1v, int it2v)
  712. {
  713. int i = 0;
  714. int j = 0;
  715. int k = 0;
  716. struct gml_node *n = NULL;
  717. int ic = 0;
  718. int ic16 = 0;
  719. int prevcross = 0;
  720. int wcross = 0;
  721. int count = 0;
  722. if (it1v) {
  723. }
  724. if (it2v) {
  725. }
  726. /* set higest level in use and number of levels */
  727. gmaxlevel = g->maxlevel;
  728. gnlevels = (gmaxlevel + 1);
  729. /* copy data */
  730. cp_data(g);
  731. /* print raw data */
  732. if (s3debug || 0) {
  733. for (i = 0; i < gnlevels; i++) {
  734. /* scan nodes at level [i] */
  735. if (sugidata[i]) {
  736. for (j = 0; j < nglevelnodes[i]; j++) {
  737. printf("%s(): node %d has %d indegree, %d outdegree\n", __func__, sugidata[i][j].id,
  738. sugidata[i][j].indegree, sugidata[i][j].outdegree);
  739. }
  740. }
  741. }
  742. }
  743. /* scan layout, but not unlimited long */
  744. for (k = 0; k < 1000; k++) {
  745. /* from top to bottom */
  746. for (j = 1; j < gmaxlevel; j++) {
  747. mediansort(g, sugidata[j], sugidata[j - 1]);
  748. }
  749. curcross = check0(g);
  750. if (curcross == 0) {
  751. /* no edge crossings */
  752. break;
  753. }
  754. /* from bottom to top */
  755. for (j = gmaxlevel; j > 0; j--) {
  756. mediansort(g, sugidata[j - 1], sugidata[j]);
  757. }
  758. curcross = check0(g);
  759. if (ic == 0) {
  760. printf("%s(): %d initial crossings\n", __func__, curcross);
  761. fflush(stdout);
  762. ic = curcross;
  763. ic = ic / 32;
  764. }
  765. if (k % 100) {
  766. printf("%s(): %d current crossings\n", __func__, curcross);
  767. fflush(stdout);
  768. }
  769. /* some way to prevent endless long layout time */
  770. if (prevcross == 0) {
  771. prevcross = curcross;
  772. } else {
  773. if (curcross == prevcross) {
  774. if (wcross == 0) {
  775. wcross = curcross;
  776. } else {
  777. if (wcross == curcross) {
  778. break;
  779. } else {
  780. wcross = 0;
  781. }
  782. }
  783. }
  784. if ((prevcross - curcross) < ic16) {
  785. break;
  786. }
  787. prevcross = curcross;
  788. }
  789. /* from top to bottom */
  790. for (j = 1; j < gmaxlevel; j++) {
  791. mediansort(g, sugidata[j - 1], sugidata[j]);
  792. }
  793. curcross = check0(g);
  794. if (curcross == 0) {
  795. /* no edge crossings */
  796. break;
  797. }
  798. /* from bottom to top */
  799. for (j = gmaxlevel; j > 0; j--) {
  800. mediansort(g, sugidata[j], sugidata[j - 1]);
  801. }
  802. curcross = check0(g);
  803. if (curcross == 0) {
  804. /* no edge crossings */
  805. break;
  806. }
  807. }
  808. printf("%s(): %d final crossings\n", __func__, curcross);
  809. fflush(stdout);
  810. /* copy new node positions */
  811. for (i = 0; i < gnlevels; i++) {
  812. count = 0;
  813. /* scan nodes at level [i] */
  814. for (j = 0; j < nglevelnodes[i]; j++) {
  815. /* extra check, must be same */
  816. if (count != sugidata[i][j].pos) {
  817. printf("%s(): at level %d pos %d found pos %d\n", __func__, i, count, sugidata[i][j].pos);
  818. }
  819. /* find the node with this id */
  820. n = uniqnode2(g, sugidata[i][j].id);
  821. if (n) {
  822. if (sugidata[i][j].level == n->rely) {
  823. /* oke and set node rel. x pos */
  824. n->relx = sugidata[i][j].pos;
  825. } else {
  826. /* shpuldnothappen */
  827. printf("%s(): node %d moved from level %d to level %d\n", __func__, n->nr, n->rely, sugidata[i][j].level);
  828. }
  829. } else {
  830. /* shpuldnothappen */
  831. printf("%s(): node id %d not found\n", __func__, sugidata[i][j].id);
  832. }
  833. count++;
  834. }
  835. }
  836. /* clear data */
  837. clr_data(g);
  838. fflush(stdout);
  839. return;
  840. }
  841. void reduce_crossings4(struct gml_graph *g, int it1v, int it2v)
  842. {
  843. int i = 0;
  844. int tsum = 0;
  845. /* number of crossing edges at level */
  846. if (g->numce) {
  847. g->numce = dp_free(g->numce);
  848. if (g->numce) {
  849. }
  850. }
  851. g->numce = (int *)dp_calloc(1, ((g->maxlevel + 1) * sizeof(int)));
  852. /* with too complex graph data at least this message is on console before cpu get roasted. */
  853. printf("%s(): starting barycenter algorithm for graph with %d nodes, %d edges in %d levels ... wait\n", __func__, g->nnodes,
  854. g->nedges, g->maxlevel + 1);
  855. fflush(stdout);
  856. if (g->maxlevel == 0) {
  857. /* if graph has only 1 or more nodes */
  858. return;
  859. }
  860. if (g->nnodes < 2) {
  861. /* only 1 node, not much todo */
  862. return;
  863. }
  864. if (g->nedges < 2) {
  865. /* only 1 level, not much todo */
  866. return;
  867. }
  868. barycenter_4(g, it1v, it2v);
  869. /* calc total number of crossings */
  870. for (i = 0; i < g->maxlevel; i++) {
  871. tsum += g->numce[i];
  872. }
  873. /* sugiyama final crossings */
  874. g->sugi_fcrossings = tsum;
  875. /* sugiyama changes made (not determined) */
  876. g->sugi_changes = 0;
  877. /* sugiyama initial crossings (not determined) */
  878. g->sugi_icrossings = 0;
  879. return;
  880. }
  881. /* end */