Member Login

Username:
Password:
Remember:

graph.html | 10.63 KB | X3no | November 28th, 2011 | 1 Downloads | 63 Views
File Name: graph.html
File Size: 10.63 KB
Uploaded By:  X3no
MD5 Hash:
SHA1 Hash:
Downloads: 1
Page Views: 63
Date Uploaded: Nov 28th, 2011 at 5:31:28 am
Last Downloaded:  Nov 28th, 2011 at 6:03:32 am
File Status:  Public File
  1. <script>
  2. function Min_Heap(data){
  3. this.data = [];
  4. }
  5. //min_heapify(i): creates a min_heap in data rooted at i
  6. //pre: i is an index in data and there are two heaps (left, right)
  7. //post: heap routed at i
  8. Min_Heap.prototype.min_heapify = function(i){
  9. //---PRECONDITION CHECK---
  10. //assert(i<this.data.length);
  11. //---END PRECONDITION CHECK---
  12. var left = (2*(i+1))-1; //left child of i
  13. var right = 2*(i+1); //right child of i
  14. var smallest = i;
  15. if (left < this.heapsize && this.data[left].key < this.data[i].key){
  16. smallest = left;
  17. }
  18. if (right < this.heapsize && this.data[right].key < this.data[smallest].key){
  19. smallest = right;
  20. }
  21. if (smallest != i){
  22. var temp = this.data[smallest];
  23. this.data[smallest] = this.data[i];
  24. this.data[i] = temp;
  25. this.min_heapify(smallest);
  26. }
  27. //---POSTCONDITION CHECK---
  28. //assert(this.data[i]);
  29. //---END POSTCONDITION CHECK---
  30. }
  31. //invarient: data[i+1]...data[n-1] are roots of min heaps (n = data.length)
  32. //pre: data is an array of size n
  33. //post: data[1]...data[n-1] are roots of min heaps
  34. Min_Heap.prototype.build_min_heap = function(){
  35. //---PRECONDITION CHECK---
  36. //assert(this.data.length);
  37. //---END PRECONDITION CHECK---
  38. this.heapsize = this.data.length;
  39. var i = Math.floor(this.heapsize/2)-1;
  40. //---INVARIENT INITILIZATION CHECK---
  41. //assert(is_min_heap(this.data, i+1, this.data.length/2-1));
  42. //---END INVARIENT INITILIZATION CHECK---
  43. for (i; i>=0; i--){
  44. this.min_heapify(i);
  45. //---INVARIENT MAINTENENCE CHECK---
  46. //assert(is_min_heap(this.data, i+1, this.data.length/2-1));
  47. //---END INVARIENT MAINTENENCE CHECK---
  48. }
  49. //---INVARIENT TERMINATION CHECK---
  50. //assert(is_min_heap(this.data, (i+1), (this.data.length/2-1)));
  51. //---END INVARIENT TERMINATION CHECK---
  52. //---POSTCONDITION CHECK---
  53. //assert(is_min_heap(this.data,0, this.data.length/2-1));
  54. //---END POSTCONDITION CHECK---
  55. }
  56. //insert an item to the min heap
  57. Min_Heap.prototype.push = function(item, key){
  58. var obj = {item: item, key: key};
  59. this.data.push(obj);
  60. this.build_min_heap();
  61. }
  62. //removes the smallest key from the min heap and rebuilds the heap
  63. Min_Heap.prototype.extract_min = function(){
  64. var min = this.data.shift();
  65. this.heapsize--;
  66. this.min_heapify(0);
  67. //Post condition: returns the smallest value from Min_heap
  68. //pc check:
  69. /*for (var i = 0; i<this.data.length; i++){
  70. assert(min.key <= this.data[i].key);
  71. }*/
  72. return min;
  73. }
  74. //checks if the heap is empty
  75. Min_Heap.prototype.empty = function(){
  76. return (this.heapsize == 0)
  77. }
  78.  
  79. //checks that A is a max heap routed at i
  80. function is_max_heap(A, i, n){
  81. if (i >= n){
  82. return true;
  83. }
  84. if (A[i].key <= A[2*(i+1)-1].key && A[i].key <= A[2*(i+1)].key && is_min_heap(A, 2*(i+1)-1, n) && is_min_heap(A, 2*(i+1), n)){
  85. return true;
  86. }
  87. else{
  88. return false;
  89. }
  90. }
  91.  
  92.  
  93. function Graph(type, num_nodes, directed){
  94. this.size = num_nodes;
  95. this.directed = directed;
  96. if (type == "matrix"){
  97. this.type = "matrix";
  98. this.matrix = new Array(num_nodes);
  99. //set up an empty n by n 2D array to be used as the matrix (n being number of nodes)
  100. for (var i = 0; i < num_nodes; i++){
  101. var temp_array = new Array(num_nodes);
  102. for (var j = 0; j <num_nodes; j++){
  103. temp_array[j] = null;
  104. }
  105. this.matrix[i] = temp_array;
  106. }
  107. }
  108. else{
  109. this.type = "list";
  110. //create an empty list of length num_nodes
  111. this.list = new Array(num_nodes);
  112. for (var i = 0; i < num_nodes; i++){
  113. this.list[i] = [];
  114. }
  115. }
  116. }
  117. //returns all nodes in graph
  118. Graph.prototype.nodes = function(){
  119. var all_nodes = new Array();
  120. //add each node to the array all_nodes
  121. for (var i = 0; i < this.size; i++){
  122. all_nodes.push(i);
  123. }
  124. return all_nodes;
  125. }
  126. //return all edges in a graph
  127. Graph.prototype.edges = function(){
  128. var all_edges = new Array();
  129. if (this.type=="matrix"){
  130. //iterate through the matrix
  131. for (var i = 0; i <this.size; i++){
  132. for (var j = 0; j<this.size; j++){
  133. if (!(this.matrix[i][j]===null)){
  134. //if an edge is found add it into the all_edges array
  135. all_edges.push({source: i, destination: j, weight: this.matrix[i][j]});
  136. }
  137. }
  138. }
  139. }
  140. else{
  141. //iterate through the list
  142. for (var i = 0; i <this.size; i++){
  143. for (var j = 0; j < this.list[i].length; j++){
  144. //for each edge add it into the all_edges array
  145. all_edges.push({source: i, destination: this.list[i][j].node, weight: this.list[i][j].weight});
  146. }
  147. }
  148. }
  149. return all_edges;
  150. }
  151. //return nodes adjacent to node
  152. Graph.prototype.adjacent = function(node){
  153. var adjacent_nodes = new Array();
  154. if (this.type=="matrix"){
  155. //iterate through node's column in the matrix
  156. for (var i = 0; i < this.size; i++){
  157. if (!(this.matrix[node][i]===null)){
  158. //if an edge is found add the adjacent node to the adjacent_nodes array
  159. adjacent_nodes.push(i);
  160. }
  161. }
  162. }else{
  163. //iterate through the adjacency list entry for node
  164. for (var i = 0; i < this.list[node].length; i++){
  165. //add each adjacent node to the adjacent_nodes array
  166. adjacent_nodes.push(this.list[node][i].node);
  167. }
  168. }
  169. return adjacent_nodes;
  170. }
  171. //return the edge weight of the edge from node1 to node2
  172. //(returns 'undefined' if an edge doesnt exist between the two nodes
  173. Graph.prototype.weight = function(node1, node2){
  174. if (this.type=="matrix"){
  175. return this.matrix[node1][node2];
  176. }
  177. else{
  178. for (var i = 0; i < this.list[node1].length; i++){
  179. if (this.list[node1][i].node == node2){
  180. //if node2 is found as an adjacent node return its weight
  181. return this.list[node1][i].weight
  182. }
  183. }
  184. }
  185. }
  186. //inserts an edge into the graph
  187. Graph.prototype.insert_edge = function(node1, node2, weight){
  188. if (this.type=="matrix"){
  189. if (this.matrix[node1][node2] === null){
  190. this.matrix[node1][node2] = weight;
  191. //make sur ethe edge doesnt already exist
  192. if (this.directed != true){
  193. //if graph is undirected insert the edge for the inverse
  194. this.matrix[node2][node1] = weight;
  195. }
  196. return true;
  197. }else{
  198. return false;
  199. }
  200. }
  201. else{
  202. for (var i = 0; i < this.list[node1].length; i++){
  203. //make sure the edge doesnt already exist
  204. if (this.list[node1][i].node == node2){
  205. return false;
  206. }
  207. }
  208. this.list[node1].push({node: node2, weight: weight});
  209. if (this.directed != true){
  210. //if graph is undirected insert the edge for the inverse
  211. this.list[node2].push({node: node1, weight: weight});
  212. }
  213. return true;
  214. }
  215. }
  216.  
  217. //Pre: no negative edge weights in connected graph G.
  218. //Post: every node is labeled by its shortest distance (dist[node]) back to the source and predeccessors[node] contains the previous node in the shortest path
  219. function dijkstras(G,s){
  220. //precondition check
  221. var edges = G.edges();
  222. for (var e in edges){
  223. if (edges[e].weight<0){
  224. alert("negative edge weight found");
  225. return;
  226. }
  227. }
  228. //end precondition check
  229.  
  230. var predecessors = new Array();
  231. var dist = new Array();
  232. dist[s] = 0;
  233. //var inPath = new Array();
  234. var queue = new Min_Heap();
  235. queue.push(s,0);
  236. while (!queue.empty()){
  237. var u = queue.extract_min().item;
  238. //inPath.push(u);
  239. for (var v in G.adjacent(u)){
  240. if (dist[v]>dist[u]+G.weight(u,v) || typeof dist[v] === 'undefined'/*undefined is treated as infinity*/){
  241. //u is the closest node to s(because it has the smallest key. (from extract_min)
  242. //the closest adjacent node is selected. -> greedy choice is made
  243. dist[v] = dist[u] + G.weight(u,v);
  244. predecessors[v] = u;
  245. queue.push(v, dist[v]+G.weight(u,v));
  246. }
  247. }
  248. }
  249. return predecessors;
  250. }
  251.  
  252. //Pre: graph G (can have negative edge weights).
  253. //Post: every node is labeled by its shortest distance (dist[node]) back to the source and predeccessors[node] contains the previous node in the shortest path
  254. function bellmanFord(G, s){
  255. var dist = new Array();
  256. var u, v;
  257. var predecessors = new Array();
  258. for (var v in G.nodes()){
  259. if (v == s){
  260. dist[v] = 0;
  261. }
  262. else{
  263. dist[v] = null;
  264. }
  265. predecessors[v] = null;
  266. }
  267. for (var i = 1; i<G.nodes().length; i++){
  268. var edge = G.edges();
  269. for (var e in edge){
  270. u = edge[e].source;
  271. v = edge[e].destination;
  272. if (dist[u] + edge[e].weight < dist[v] || dist[v] === null){
  273. dist[v] = dist[u] + edge[e].weight
  274. predecessors[v] = u;
  275. }
  276. }
  277. }
  278. for (var e in G.edges()){
  279. u = e.source;
  280. v = e.destination;
  281. if (dist[u] + e.weight < dist[v]){
  282. alert("Negative edge weight cycle found");
  283. }
  284. }
  285. return predecessors;
  286. }
  287.  
  288. //function used to extract the shortest path to a given destination from the predecessor array
  289. function getShortestPath(predecessors, destination){
  290. var d = destination;
  291. var nodes = [];
  292. var u = d;
  293. var predecessor;
  294. while (u){
  295. nodes.push(u);
  296. predecessor = predecessors[u];
  297. u = predecessors[u];
  298. }
  299. nodes.reverse();
  300. return nodes;
  301. }
  302. //generates a random graph by inserting a number of random edges equal to num_v squared times density
  303. function generate_graph_vers1(num_v, density, directed, min_weight, max_weight){
  304. var G = new Graph("matrix", num_v, directed);
  305. var G2 = new Graph("list", num_v, directed);
  306. if (directed==true){
  307. var num_edges = Math.floor(density*((num_v*num_v)));
  308. }
  309. else{
  310. var num_edges = Math.floor(density*((num_v*num_v)/2));
  311. }
  312. var i = 0;
  313. while(i < num_edges){
  314. var ind1 = Math.floor(Math.random()*(num_v));
  315. var ind2 = Math.floor(Math.random()*(num_v));
  316. var weight = Math.floor(Math.random()*(max_weight-min_weight))+min_weight;
  317. if (G.insert_edge(ind1, ind2, weight)){
  318. G2.insert_edge(ind2, ind2, weight);
  319. i++;
  320. }
  321. }
  322. return {matrix: G, list: G2};
  323. }
  324. //generates a random graph by inserting random edges with a probability of density between each set of vertices
  325. function generate_graph_vers2(num_v, density, directed, min_weight, max_weight){
  326. var G = new Graph("matrix", num_v, directed);
  327. var G2 = new Graph("list", num_v, directed);
  328. var i = 0;
  329. for (var i = 0; i < num_v; i++){
  330. for (var j = 0; j < num_v; j++){
  331. if (Math.random() <= density){
  332. var weight = Math.floor(Math.random()*(max_weight-min_weight))+min_weight;
  333. G.insert_edge(i, j, weight);
  334. G2.insert_edge(i, j, weight);
  335. }
  336. }
  337. }
  338. return {matrix: G, list: G2};
  339. }
  340.  
  341. function test_SSSP(G, alg, type){
  342. var d = new Date();
  343. d = d.getTime();
  344. if (type=="matrix"){
  345. var g = G.matrix;
  346. }else{
  347. var g = G.list;
  348. }
  349. if (alg[0]=="d"){
  350. dijkstras(g,0);
  351. }else{
  352. bellmanFord(g,0);
  353. }
  354. var d2 = new Date();
  355. d2 = d2.getTime();
  356. var runtime = d2-d;
  357. console.log(runtime);
  358. }
  359.  
  360. var G = generate_graph_vers1(10,.5, false, 1,10);
  361. console.log(G);
  362. var p = dijkstras(G.matrix, 2);
  363. var p2 = dijkstras(G.list, 2);
  364. var p3 = bellmanFord(G.matrix, 2);
  365. var p4 = bellmanFord(G.list, 2);
  366.  
  367.  
  368. </script>
  369.  
 
By downloading this file, you agree to our Terms of Service and Privacy Policy. If this file violates our terms of service, please report it. Report file