Advertisement
Guest User

Untitled

a guest
Aug 3rd, 2015
181
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 7.21 KB | None | 0 0
  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <meta charset="utf-8">
  5. <title>Affinity Propagation clustering</title>
  6. <script src="./jquery-2.1.3.min.js"></script>
  7. <script>
  8. function getRandomInt(min, max) {
  9. return Math.floor(Math.random() * (max - min + 1)) + min;
  10. }
  11. function distance(p, q) {
  12. return Math.sqrt(Math.pow(p.x - q.x, 2.0) + Math.pow(p.y - q.y, 2.0));
  13. }
  14. function median(values) {
  15. values.sort( function(a,b) {return a - b;} );
  16.  
  17. var half = Math.floor(values.length/2);
  18.  
  19. if(values.length % 2)
  20. return values[half];
  21. else
  22. return (values[half-1] + values[half]) / 2.0;
  23. }
  24. function drawArrow(ctx, fromx, fromy, tox, toy){
  25. var color = 'rgba(204, 0, 0, 0.5)'
  26. var headlen = 5;
  27. var angle = Math.atan2(toy-fromy,tox-fromx);
  28.  
  29. //starting path of the arrow from the start square to the end square and drawing the stroke
  30. ctx.beginPath();
  31. ctx.moveTo(fromx, fromy);
  32. ctx.lineTo(tox, toy);
  33. ctx.strokeStyle = color;
  34. ctx.lineWidth = 2;
  35. ctx.stroke();
  36.  
  37. //starting a new path from the head of the arrow to one of the sides of the point
  38. ctx.beginPath();
  39. ctx.moveTo(tox, toy);
  40. ctx.lineTo(tox-headlen*Math.cos(angle-Math.PI/7),toy-headlen*Math.sin(angle-Math.PI/7));
  41.  
  42. //path from the side point of the arrow, to the other side point
  43. ctx.lineTo(tox-headlen*Math.cos(angle+Math.PI/7),toy-headlen*Math.sin(angle+Math.PI/7));
  44.  
  45. //path from the side point back to the tip of the arrow, and then again to the opposite side point
  46. ctx.lineTo(tox, toy);
  47. ctx.lineTo(tox-headlen*Math.cos(angle-Math.PI/7),toy-headlen*Math.sin(angle-Math.PI/7));
  48.  
  49. //draws the paths created above
  50. ctx.strokeStyle = color;
  51. ctx.lineWidth = 2;
  52. ctx.stroke();
  53. ctx.fillStyle = color;
  54. ctx.fill();
  55. }
  56.  
  57. var canvas, data, N, iter, isAuto = false,
  58. preference, lambda = 0.9,
  59. similarities, availabilities, responsibilities;
  60.  
  61. function plot(withCentroidMarker) {
  62. if (arguments.length == 0) {
  63. withCentroidMarker = true;
  64. }
  65. var ctx = canvas.getContext("2d");
  66. ctx.clearRect(0, 0, canvas.width, canvas.height);
  67. for (var i = 0; i < N; ++i) {
  68. var p = data[i];
  69. ctx.lineWidth = 2;
  70. ctx.fillStyle = 'black';
  71. ctx.beginPath();
  72. ctx.fillRect(p.x - 3, p.y - 3, 6, 6);
  73. if (p.klass == i) {
  74. if (withCentroidMarker) {
  75. ctx.strokeStyle = 'black';
  76. ctx.beginPath();
  77. ctx.arc(p.x, p.y, 5, 0, Math.PI * 2, false);
  78. ctx.stroke();
  79. }
  80. } else {
  81. drawArrow(ctx, p.x, p.y, data[p.klass].x, data[p.klass].y);
  82. }
  83. }
  84. }
  85.  
  86. function init(n) {
  87. var flatsim = new Array();
  88. iter = 0;
  89. $('#iter').text(iter);
  90. N = n;
  91. similarities = new Array(N);
  92. responsibilities = new Array(N);
  93. availabilities = new Array(N);
  94.  
  95. /*
  96. data = [[135,183],[184,94],[24,131],[144,36],[207,106],[202,102],[164,69],[156,173],[230,95],[84,35],[76,181],[230,136],[157,147],[80,115],[119,211],[56,95],[215,101],[226,87],[185,15],[163,31],[186,159],[108,50],[203,88],[34,182],[16,179]].map(function(arr) {
  97. return {x: arr[0], y: arr[1], klass: -1};
  98. });
  99. for (var i = 0; i < N; ++i) {
  100. data[i].klass = i;
  101. }
  102. */
  103. data = new Array(N);
  104. for (var i = 0; i < N; ++i) {
  105. data[i] = {x: getRandomInt(10, canvas.width - 10), y: getRandomInt(10, canvas.height - 10), klass: i};
  106. }
  107. for (var i = 0; i < N; ++i) {
  108. similarities[i] = new Array(N);
  109. for (var j = 0; j < N; ++j) {
  110. var s = -distance(data[i], data[j]);
  111. similarities[i][j] = s;
  112. if (i != j)
  113. flatsim.push(s);
  114. }
  115. }
  116. preference = median(flatsim);
  117. // preference = flatsim.sort(function(a, b) { return a - b; })[0];
  118. $('#preference').text(preference);
  119. for (var i = 0; i < N; ++i) {
  120. similarities[i][i] = preference;
  121. }
  122.  
  123. for (var i = 0; i < N; ++i) {
  124. responsibilities[i] = new Array(N);
  125. for (var j = 0; j < N; ++j) {
  126. responsibilities[i][j] = 0;
  127. }
  128. }
  129. for (var i = 0; i < N; ++i) {
  130. availabilities[i] = new Array(N);
  131. for (var j = 0; j < N; ++j) {
  132. availabilities[i][j] = 0;
  133. }
  134. }
  135. };
  136.  
  137. function updateResponsibilities() {
  138. for (var i = 0; i < N; ++i) {
  139. var m1 = -Infinity, m2 = -Infinity, idx;
  140. for (var k = 0; k < N; ++k) {
  141. var score = availabilities[i][k] + similarities[i][k];
  142. if (m1 < score) {
  143. m2 = m1;
  144. m1 = score;
  145. idx = k;
  146. } else if (m2 < score) {
  147. m2 = score;
  148. }
  149. }
  150.  
  151. for (var k = 0; k < N; ++k) {
  152. var rold = responsibilities[i][k],
  153. rnew = similarities[i][k] - (k == idx ? m2 : m1);
  154. responsibilities[i][k] = lambda * rold + (1 - lambda) * rnew;
  155. }
  156. }
  157. }
  158.  
  159. function updateAvailabilities() {
  160. for (var i = 0; i < N; ++i) {
  161. var Rp = new Array(N), sum = 0;
  162. for (var k = 0; k < N; ++k) {
  163. Rp[k] = (responsibilities[k][i] < 0 && k != i) ? 0 : responsibilities[k][i];
  164. sum += Rp[k];
  165. }
  166.  
  167. for (var k = 0; k < N; ++k) {
  168. var aold = availabilities[k][i],
  169. anew = sum - Rp[k];
  170. if (anew > 0 && k != i) {
  171. anew = 0;
  172. }
  173. availabilities[k][i] = (1 - lambda) * anew + lambda * aold;
  174. }
  175. }
  176. }
  177.  
  178. function assign() {
  179. for (var i = 0; i < N; ++i) {
  180. var maxScore = -Infinity, maxScoreIndex = -Infinity;
  181. for (var k = 0; k < N; ++k) {
  182. var score = responsibilities[i][k] + availabilities[i][k];
  183. if (maxScore < score) {
  184. maxScore = score;
  185. maxScoreIndex = k;
  186. }
  187. }
  188. data[i].klass = maxScoreIndex;
  189. }
  190. }
  191.  
  192. function step() {
  193. updateResponsibilities();
  194. updateAvailabilities();
  195. assign();
  196. ++iter;
  197. $('#iter').text(iter);
  198. }
  199.  
  200. $(function() {
  201. var n = 20;
  202. canvas = document.getElementById("canvas");
  203. $('#step').click(function() { step(); plot(); });
  204. $('#init').click(function() { init(n); plot(false); });
  205. $('#start').click(function() { isAuto = true; });
  206. $('#stop').click(function() { isAuto = false; });
  207. setInterval(function() { if (isAuto) { step(); plot(); } }, 50);
  208. init(n);
  209. plot(false);
  210. });
  211. </script>
  212. </head>
  213. <body>
  214. <canvas id="canvas" width="240" height="240">
  215. canvas is not available
  216. </canvas>
  217. <br>
  218. <button id="init">Init</button>
  219. <button id="step">Step</button>
  220. <button id="start">Auto</button>
  221. <button id="stop">Stop</button>
  222. <p>Iter: <span id="iter"></span></p>
  223. <p>Preference: <span id="preference"></span></p>
  224. </body>
  225. </html>
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement