diff war/scripts/sti/kruskal.js @ 3:cf06b77a8bbd

Committed branch of the e4D repos sti-gwt branch 16384. git-svn-id: http://dev.dariah.eu/svn/repos/eu.dariah.de/ap1/sti-gwt-dariah-geobrowser@36 f2b5be40-def6-11e0-8a09-b3c1cc336c6b
author StefanFunk <StefanFunk@f2b5be40-def6-11e0-8a09-b3c1cc336c6b>
date Tue, 17 Jul 2012 13:34:40 +0000
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/war/scripts/sti/kruskal.js	Tue Jul 17 13:34:40 2012 +0000
@@ -0,0 +1,259 @@
+var infinity = 100000000000; // !!! beware, not allowable for many applications
+
+function Edge2(a, b, w) { this.v1=a; this.v2=b; this.wt=w; }
+
+function setEdgeAdjMatrix(i, j, w)
+ { if(j > i) { var t=i; i=j; j=t; }//swap so that i >= j
+   this.matrix[i][j] = w;
+ }
+
+
+function randomAdjMatrix(pr) // allocate random edges with probability 'pr'; LA
+ { var i, j;
+   for(i=0; i < this.Vertices; i++)
+    { for(j=0; j < i; j++)
+       { if(Math.random() <= pr)//LAllison, roll dice
+            this.setEdge(i, j, 1+Math.round(Math.random()*8));  // wt in [1..9]
+ }  }  }//randomAdjMatrix
+
+
+function edgeWeightAdjMatrix(i,j)
+ { return i >= j ? this.matrix[i][j] : this.matrix[j][i]; }
+
+function adjacentAdjMatrix(i, j)
+ { return this.edgeWeight(i,j) < infinity; }
+
+
+function AdjMatrix(Vrtcs)  // constructor for a Graph as an Adjacency Matrix
+ { this.Vertices   = Vrtcs;                    // Vertices [0..Vrtcs-1]
+   this.edgeWeight = edgeWeightAdjMatrix;      // These functions
+   this.adjacent   = adjacentAdjMatrix;        // and values
+   this.random     = randomAdjMatrix;
+   this.setEdge    = setEdgeAdjMatrix;
+
+   this.matrix = new Array(Vrtcs);             // the Graph representation...
+   var i, j;
+   for(i=0; i < Vrtcs; i++)                    // undirected graph so...
+    { this.matrix[i] = new Array(i+1);         // symmetric => triangular !!!
+      for(j=0; j <= i; j++)
+         this.setEdge(i, j, infinity);         // no edges, yet
+    }
+ }//AdjMatrix
+
+//-----------------------------------------------------------------------------
+
+function AdjListCell(vert, w, next)
+ { this.v = vert; this.wt = w; this.tl = next; }
+
+function AdjListFromAdjMatrix(GbyMatrix)
+ { var v1, v2;
+   this.Vertices = GbyMatrix.Vertices;
+
+   for(v1=0; v1 < this.Vertices; v1++)
+    { this.vertex[v1] = null;  // clear
+
+      for(v2=this.Vertices-1; v2 >= v1; v2--)  // v1 <= v2
+       { if(GbyMatrix.adjacent(v1, v2))
+          { var wt = GbyMatrix.edgeWeight(v1, v2);
+            this.vertex[v1] = new AdjListCell(v2, wt, this.vertex[v1]);
+          }
+       }
+    }
+ }//AdjListFromAdjMatrix
+
+function AdjList(Vrtcs) // Constructor for a Graph by Adjacency Lists         C
+ { this.Vertices      = Vrtcs;                                             // o
+   this.fromAdjMatrix = AdjListFromAdjMatrix;                              // m
+                                                                           // p
+   this.vertex   = new Array(Vrtcs);  // set up the adjacency lists           .
+   var i;                                                                  // S
+   for(i=0; i < Vrtcs; i++) this.vertex[i]=null;                           // c
+ }//AdjList                                                                   i
+
+//-----------------------------------------------------------------------------
+
+function Prim(G)
+// Post: T[] is a minimum spanning tree of G and
+//       T[i-1] is the edge linking Vertex i into the tree
+// Time complexity is O(|V|**2)
+ { var T = new Array(G.Vertices-1);
+   var i;
+   var done = new Array(G.Vertices);
+
+   done[0] = true;                               // initially T=<{0},{ }>
+   for(i = 1; i < G.Vertices; i++)
+    { T[i-1] = new Edge2(0, i, G.edgeWeight(0,i));
+      done[i]=false;
+    }
+
+   var dontCare;
+   for(dontCare = 1; dontCare < G.Vertices; dontCare++)// |V|-1 times...      L
+   // Invariant: T is a min' spanning sub-Tree of vertices in done            A
+    { // find the undone vertex that is closest to the Spanning (sub-)Tree    l
+      var minDist = infinity, closest = -1;                                // l
+      for(i = 1; i < G.Vertices; i++)                                      // i
+         if(! done[i] && T[i-1].wt <= minDist)                             // s
+          { minDist = T[i-1].wt; closest = i; }                            // o
+      done[closest] = true;                                                // n
+
+      for(i=1; i < G.Vertices; i++) // recompute undone proximities to T
+         if(! done[i])
+          { var Gci = G.edgeWeight(closest, i);
+            if(Gci < T[i-1].wt)
+             { T[i-1].wt = Gci;
+               T[i-1].v1 = closest;
+    }     }  }
+
+   return T;
+ }//Prim
+
+// ----------------------------------------------------------------------------
+
+function PartitionMerge(s1, s2)
+// merge the smaller of subsets s1 and s2 into the larger of them.            M
+ { var drop, keep;                                                         // o
+   if(this.subset[s1].nElts < this.subset[s2].nElts) // drop the smaller      n
+    { drop=s1; keep=s2; }                                                  // a
+   else                                                                    // s
+    { drop=s2; keep=s1; }                                                  // h
+
+   var dropElt = this.subset[drop].firstElt; // each element in smaller subset
+   var done=false;
+   while(! done)
+    { this.elt[dropElt].setNumber = keep; // move the element to larger subset
+      if( this.elt[dropElt].nextElt < 0)
+         done = true;
+      else
+         dropElt = this.elt[dropElt].nextElt;
+    }//end while
+
+   this.elt[dropElt].nextElt  = this.subset[keep].firstElt;      // join lists
+   this.subset[keep].firstElt = this.subset[drop].firstElt;
+   this.subset[keep].nElts   += this.subset[drop].nElts;
+
+   this.subset[drop].firstElt = -1;  // clear smaller subset
+   this.subset[drop].nElts = 0;
+
+   this.size --;                           // one less subset in the partition
+ }//PartitionMerge
+
+
+function PartitionEltCell(sn, nxt) { this.setNumber = sn; this.nextElt = nxt; }
+
+function PartitionSetCell(ne, fst) { this.nElts = ne; this.firstElt = fst; }
+
+
+function PartitionSingletons() // make {{0}, {1}, {2}, ...}
+ { var i;
+   this.size = (this.elt).length; // # of subsets in the partition
+   for(i=0; i < this.size; i++)
+    { this.elt[i] = new PartitionEltCell(i, -1);
+      this.subset[i] = new PartitionSetCell(1, i); // i.e. i is in {i}
+ }  }
+
+
+function Partition(N)                                                      // A
+ { this.elt    = new Array(N); // elements -> subsets                         l
+   this.subset = new Array(N); // subsets -> elements                         l
+                                                                           // i
+   this.singletons = PartitionSingletons;                                  // s
+   this.merge      = PartitionMerge;                                       // o
+ }//Partition constructor                                                     n
+
+
+function upHeap(e) // see PriorityQ                                           L
+// add e to the (smallest on top) heap, arr[1..size]                          A
+//  PRE: arr[1..size] is a (smallest at top) heap / priority Q                l
+// POST: arr[1..size] is a (bigger) heap, with e added                        l
+ { this.size++;                                                            // i
+   var child = this.size,  parent;                                         // s
+   while(child > 1)//i.e. not top of heap                                  // o
+    { parent = Math.floor(child / 2);                                      // n
+
+      if(this.arr[parent].wt > e.wt)
+         this.arr[child] = this.arr[parent];   // move parent down
+      else
+         break;                                // found a place for e
+      child = parent;
+    }
+
+   // either child==1, i.e. parentless, or parent is less than or eq to e
+   this.arr[child] = e;
+ }//upHeap, L.Allison, Comp Sci and Software Engineering, Monash University
+
+
+function downHeap(e)
+// add e to the (smallest on top) heap, arr[2..size]
+//  PRE: arr[2..size] is a heap
+// POST: arr[1..size] is a heap
+ { var parent = 1,  child;                                                 // A
+   while(2*parent <= this.size)                                            // U
+    { child = 2*parent; // left child is 2*parent, right is 2*parent+1     // S
+                                                                           // T
+      if(child < this.size && this.arr[child+1].wt < this.arr[child].wt)   // R
+         child++; // right child is smaller then left child                // A
+                                                                           // L
+      if(this.arr[child].wt < e.wt)                                        // I
+         this.arr[parent] = this.arr[child];   // move the child up        // I
+      else                                                                 // A
+         break;                                // found a place for e
+      parent = child;
+    }
+
+   // either parent childless or child(ren) of parent are greater or eq to e
+   this.arr[parent] = e;
+ }//downHeap, L.Allison, Comp Sci and Software Engineering, Monash University
+
+
+function topHeap()
+// PRE: this.size > 0
+ { var ans = this.arr[1];                                                  // C
+   this.size--;                                                            // S
+   if(this.size <= 0) return ans;                                          // S
+   //else                                                                  // E
+   this.downHeap(this.arr[this.size+1]);
+   return ans;
+ }
+
+
+function PriorityQ()                                                       // A
+ { this.arr  = new Array(); // NB. never use arr[0]                           l
+   this.size = 0; // so far                                                   l
+                                                                           // i
+   this.pushq = upHeap;                                                    // s
+   this.popq  = topHeap; this.downHeap = downHeap;                         // o
+ }//constructor                                                               n
+
+
+function Kruskal(G)                                                        // L
+// G is a graph implemented by adjacency lists!                               A
+// return a minimum spanning tree, T                                          l
+ { var i;                                                                  // l
+   var T = new Array();         // to be the min' spanning tree               i
+                                                                           // s
+   var Q = new PriorityQ();                                                // o
+                                                                           // n
+   for(i=0; i < G.Vertices; i++)//first make a PriorityQ of all the edges of G
+    { var Gi = G.vertex[i];
+      while(Gi != null)         // i.e. for each edge {i,v}
+       { Q.pushq(new Edge2(i, Gi.v, Gi.wt));
+         Gi = Gi.tl;
+       }
+    }
+
+   var n = 0;                                               // Computer Science
+   var P = new Partition(G.Vertices);                                      // M
+   P.singletons();                                                         // o
+   while(P.size > 1)            // the min' spanning tree algorithm proper    n
+    { if(Q.size <= 0)           // G disconnected                             a
+        break;                                                             // s
+                                                                           // h
+      var e = Q.popq();         // shortest edge
+      if(P.elt[e.v1].setNumber != P.elt[e.v2].setNumber)                   // U
+       { T[n] = e;  n++;                                                   // n
+         P.merge(P.elt[e.v1].setNumber, P.elt[e.v2].setNumber);            // i
+       }
+    }
+
+   return T;
+ }//Kruskal,  NB. can work on adjacency matrix, but is best on sparse graphs.