//Stacked MST public static LightWeightGraph GetStackedMST(DistanceMatrix distances, int numMSTs) { int numNodes = distances.Count; //in a complete graph, there are n*(n-1)/2 edges //an MST contains n-1 edges //number of msts is n/2 if (numMSTs > numNodes / 2) { numMSTs = numNodes / 2; } LightWeightNode[] nodes = new LightWeightNode[numNodes]; List <int>[] edges = new List <int> [numNodes]; List <double>[] weights = new List <double> [numNodes]; //List<double>[] edgeWeights = new List<double>[numNodes]; for (int i = 0; i < numNodes; i++) { edges[i] = new List <int>(); weights[i] = new List <double>(); } //Add all of the distances to the Heap List <distXY> points = new List <distXY>(); for (int x = 0; x < numNodes - 1; x++) { for (int y = x + 1; y < numNodes; y++) { points.Add(new distXY(x, y, distances[x, y])); } } //Now we need to start making our MST for (int n = 0; n < numMSTs; n++) { MinHeapPriorityQueue <distXY> minheap = new MinHeapPriorityQueue <distXY>(((x, y) => x.Dist > y.Dist)); minheap.addAll(points); DisjointSet ds = new DisjointSet(numNodes); int k = 0; while (k < numNodes - 1) { distXY e = minheap.extractMin(); if (ds.diff(e.X, e.Y)) //different { ds.union(e.X, e.Y); //change the dist e.Dist = double.MaxValue; //Add it edges[e.X].Add(e.Y); edges[e.Y].Add(e.X); weights[e.X].Add(distances[e.X, e.Y]); weights[e.Y].Add(distances[e.X, e.Y]); k++; } } } for (int i = 0; i < numNodes; i++) { nodes[i] = new LightWeightNode(i, true, edges[i], weights[i]); } return(new LightWeightGraph(nodes, true)); }
//Knn based public static LightWeightGraph GetKNNGraph(DistanceMatrix distances, int numNeighbors) { int numNodes = distances.Count; var nodes = new LightWeightNode[numNodes]; List <int>[] edgeLists = new List <int> [numNodes]; List <double>[] edgeWeights = new List <double> [numNodes]; for (int i = 0; i < numNodes; i++) { edgeLists[i] = new List <int>(); edgeWeights[i] = new List <double>(); } //prevent redundant edges HashSet <Tuple <int, int> > addedEdges = new HashSet <Tuple <int, int> >(); //Our comparator MinHeapPriorityQueue <Tuple <int, double> > .isGreaterThan comp = new MinHeapPriorityQueue <Tuple <int, double> > .isGreaterThan((x, y) => { return(x.Item2 > y.Item2); }); //Add Edges for (int i = 0; i < numNodes; i++) { //get list of edges List <Tuple <int, double> > edges = new List <Tuple <int, double> >(); for (int j = 0; j < numNodes; j++) { //Make sure we don't load our heap with repeated edges if (i != j) { edges.Add(new Tuple <int, double>(j, distances[i, j])); } } //Build the heap MinHeapPriorityQueue <Tuple <int, double> > heap = new MinHeapPriorityQueue <Tuple <int, double> >(comp); heap.addAll(edges); //Now add all of the neighbors for (int edgeNum = 0; edgeNum < numNeighbors; edgeNum++) { if (heap.isEmpty()) { break; } Tuple <int, double> e = heap.extractMin(); Tuple <int, int> edgeNodePair = (e.Item1 < i) ? new Tuple <int, int>(e.Item1, i) : new Tuple <int, int>(i, e.Item1); //if (!addedEdges.Contains(edgeNodePair)) if (!addedEdges.Contains(edgeNodePair)) { //make sure we don't add this edge again in the future //addedEdges.Add(edgeNodePair); addedEdges.Add(edgeNodePair); //Add the double edge now edgeLists[i].Add(e.Item1); edgeLists[e.Item1].Add(i); edgeWeights[i].Add((double)e.Item2); edgeWeights[e.Item1].Add((double)e.Item2); } } } for (int i = 0; i < numNodes; i++) { nodes[i] = new LightWeightNode(i, true, edgeLists[i], edgeWeights[i]); } return(new LightWeightGraph(nodes, true)); }
public LightWeightGraph GetLOOGraph(DistanceMatrix distances, int numNeighbors, bool[] exclusion = null, int numToLeaveOut = 0) { int numNodes = distances.Count; var nodes = new LightWeightGraph.LightWeightNode[numNodes]; List <int>[] edgeLists = new List <int> [numNodes]; List <double>[] edgeWeights = new List <double> [numNodes]; for (int i = 0; i < numNodes; i++) { edgeLists[i] = new List <int>(); edgeWeights[i] = new List <double>(); } //prevent redundant edges HashSet <Tuple <int, int> > addedEdges = new HashSet <Tuple <int, int> >(); //Our comparator MinHeapPriorityQueue <Tuple <int, double> > .isGreaterThan comp = ((x, y) => x.Item2 > y.Item2); //Deal with _skipLast Choice int lastNeighbor = (_skipLast) ? numNodes - 1 : numNodes; //Add Edges for (int i = 0; i < lastNeighbor; i++) { if (exclusion != null && exclusion[i]) { continue; } // Deal with the leave one out double probability = (double)numToLeaveOut / numNodes; double rollDie = rnd.NextDouble(); if (rollDie < probability) { //Console.WriteLine("Skipped Node " + i); _numLeftOut++; continue; } //get list of edges List <Tuple <int, double> > edges = new List <Tuple <int, double> >(); for (int j = 0; j < numNodes; j++) { //Make sure we don't load our heap with repeated edges if (i != j) { edges.Add(new Tuple <int, double>(j, distances[i, j])); } } //Build the heap MinHeapPriorityQueue <Tuple <int, double> > heap = new MinHeapPriorityQueue <Tuple <int, double> >(comp); heap.addAll(edges); //Now add all of the neighbors for (int edgeNum = 0; edgeNum < numNeighbors; edgeNum++) { if (heap.isEmpty()) { break; } Tuple <int, double> e = heap.extractMin(); Tuple <int, int> edgeNodePair = (e.Item1 < i) ? new Tuple <int, int>(e.Item1, i) : new Tuple <int, int>(i, e.Item1); //if (!addedEdges.Contains(edgeNodePair)) if (!addedEdges.Contains(edgeNodePair)) { //make sure we don't add this edge again in the future //addedEdges.Add(edgeNodePair); addedEdges.Add(edgeNodePair); //Add the double edge now edgeLists[i].Add(e.Item1); edgeLists[e.Item1].Add(i); edgeWeights[i].Add((double)e.Item2); edgeWeights[e.Item1].Add((double)e.Item2); } } } for (int i = 0; i < numNodes; i++) { nodes[i] = new LightWeightGraph.LightWeightNode(i, true, edgeLists[i], edgeWeights[i]); } return(new LightWeightGraph(nodes, true)); }