You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

GraphEditDistance.m 3.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  1. function [ best_dist ] = GraphEditDistance( g1, g2, num_missing_nodes)
  2. %GraphEditDistance - calculate the distance between two graphs with missing
  3. %nodes
  4. % Detailed explanation goes here
  5. %simulated annealing parameters
  6. c = 0.9;
  7. start_temp = 1000;
  8. t = start_temp;
  9. round = 0;
  10. n = size(g1,1);
  11. m = size(g2,1);
  12. %get the maximal size of the two graphs
  13. N = max(n,m);
  14. %if the number of missing nodes is not given, perform the search on all the
  15. %nodes
  16. if nargin < 3
  17. num_missing_nodes = N;
  18. end
  19. max_iterations = N;
  20. init_distance = 0;
  21. %make the two graphs the same size by padding zeros
  22. if n < N
  23. %g1 is smaller, make it NxN
  24. g1(N,N) = 0;
  25. %the penalty is N-n because we added this number of nodes
  26. init_distance = N - n;
  27. end
  28. if m < N
  29. %g2 is smaller, make it NxN and add a penalty of N-m
  30. g2(N,N) = 0;
  31. init_distance = N - m;
  32. end
  33. %%%distance = sum(sum(abs(g1 - g2))) / 2;
  34. best_dist = Inf;
  35. for restart = 1 : N*N/4 % sigal 24.12.12 - add 1/4 factor as no improvement seen after N*N/4
  36. %create a matching vector between the two matrices
  37. %the first K nodes are known nodes and therefore they match (where
  38. %K = N-num_missing_nodes
  39. %the vector will look like this:
  40. %[1,2,3,...,K, ***random permutation of the numbers between K+1 and N***]
  41. matching= [1:N-num_missing_nodes, randperm(num_missing_nodes) + N - num_missing_nodes];
  42. try
  43. %transform g2 according to the permutation, simply by switching
  44. %rows and columns according to the matching vector
  45. perm_graph = g2(matching, matching);
  46. catch ME1
  47. x = 90;
  48. end
  49. num_failures = 0;
  50. iter = 0;
  51. while num_failures < N %&& iter < max_iterations
  52. iter = iter+1;
  53. i = randi(num_missing_nodes,1) + N - num_missing_nodes;
  54. j = randi(num_missing_nodes,1) + N - num_missing_nodes;
  55. %should we swap i and j?
  56. row_i = perm_graph(i,:);
  57. row_j = perm_graph(j,:);
  58. %calculate the current distance due to rows i and j
  59. curr_dist = sum(abs(g1(i,:) - row_i)) + sum(abs(g1(j,:) - row_j));
  60. temp = row_i(i);
  61. row_i(i) = row_i(j);
  62. row_i(j) = temp;
  63. temp = row_j(i);
  64. row_j(i) = row_j(j);
  65. row_j(j) = temp;
  66. %calculate the distance due to rows i and j after swapping them
  67. new_dist = sum(abs(g1(i,:) - row_j)) + sum(abs(g1(j,:) - row_i));
  68. %if swapping causes an improvement, or randomly according to
  69. %simulated annealing:
  70. if new_dist < curr_dist || (rand(1) < exp( - (new_dist - curr_dist) / (c*t) ) && new_dist ~= curr_dist)
  71. %temp = exp( - (new_dist - curr_dist) / (c*t) )
  72. %swap the "matching" indexes
  73. temp = matching(i);
  74. matching(i) = matching(j);
  75. matching(j) = temp;
  76. %swap rows i and j
  77. temp = perm_graph(i,:);
  78. perm_graph(i,:) = perm_graph(j,:);
  79. perm_graph(j,:) = temp;
  80. %swap columns i and j
  81. temp = perm_graph(:,i);
  82. perm_graph(:,i) = perm_graph(:,j);
  83. perm_graph(:,j) = temp;
  84. num_failures = 0;
  85. round = round+1;
  86. t = t*c;
  87. else
  88. num_failures = num_failures + 1;
  89. end
  90. end
  91. distance = sum(sum(abs(g1 - perm_graph)));
  92. if distance < best_dist
  93. best_dist = distance;
  94. fprintf('restart %d, best_dist %d, N %d\n', full(restart), full(best_dist), full(N));
  95. end
  96. end
  97. %divide by 2 due to symmetry
  98. best_dist = best_dist / 2 + init_distance;
  99. end