opt_arrangement.c 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990
  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. #include <neatogen/digcola.h>
  11. #include <util/alloc.h>
  12. #ifdef DIGCOLA
  13. #include <neatogen/matrix_ops.h>
  14. #include <neatogen/conjgrad.h>
  15. #include <stddef.h>
  16. static void construct_b(vtx_data * graph, int n, double *b)
  17. {
  18. /* construct a vector - b s.t. -b[i]=\sum_j -w_{ij}*\delta_{ij}
  19. * (the "balance vector")
  20. * Note that we build -b and not b, since our matrix is not the
  21. * real laplacian L, but its negation: -L.
  22. * So instead of solving Lx=b, we will solve -Lx=-b
  23. */
  24. int i;
  25. double b_i = 0;
  26. for (i = 0; i < n; i++) {
  27. b_i = 0;
  28. if (graph[0].edists == NULL) {
  29. continue;
  30. }
  31. for (size_t j = 1; j < graph[i].nedges; j++) { // skip the self loop
  32. b_i += graph[i].ewgts[j] * graph[i].edists[j];
  33. }
  34. b[i] = b_i;
  35. }
  36. }
  37. #define hierarchy_cg_tol 1e-3
  38. int
  39. compute_y_coords(vtx_data * graph, int n, double *y_coords,
  40. int max_iterations)
  41. {
  42. /* Find y coords of a directed graph by solving L*x = b */
  43. int i, rv = 0;
  44. double *b = gv_calloc(n, sizeof(double));
  45. double tol = hierarchy_cg_tol;
  46. size_t nedges = 0;
  47. float *old_ewgts = graph[0].ewgts;
  48. construct_b(graph, n, b);
  49. init_vec_orth1(n, y_coords);
  50. for (i = 0; i < n; i++) {
  51. nedges += graph[i].nedges;
  52. }
  53. /* replace original edge weights (which are lengths) with uniform weights */
  54. /* for computing the optimal arrangement */
  55. float *uniform_weights = gv_calloc(nedges, sizeof(float));
  56. for (i = 0; i < n; i++) {
  57. graph[i].ewgts = uniform_weights;
  58. uniform_weights[0] = -(float)(graph[i].nedges - 1);
  59. for (size_t j = 1; j < graph[i].nedges; j++) {
  60. uniform_weights[j] = 1;
  61. }
  62. uniform_weights += graph[i].nedges;
  63. }
  64. if (conjugate_gradient(graph, y_coords, b, n, tol, max_iterations) < 0) {
  65. rv = 1;
  66. }
  67. /* restore original edge weights */
  68. free(graph[0].ewgts);
  69. for (i = 0; i < n; i++) {
  70. graph[i].ewgts = old_ewgts;
  71. old_ewgts += graph[i].nedges;
  72. }
  73. free(b);
  74. return rv;
  75. }
  76. #endif /* DIGCOLA */