/// <summary> /// Creates a thresholded geometric graph /// </summary> /// <param name="d">distance matrix used to construct the graph</param> /// <param name="threshold">the maximum allowed distance</param> /// <returns></returns> public static LightWeightGraph GetGeoGraph(DistanceMatrix d, double threshold) { //construct the geo graph int numNodes = d.Count; var nodes = new LightWeightGraph.LightWeightNode[numNodes]; //Create a list to hold edge values List <int>[] edges = new List <int> [numNodes]; List <double>[] weights = new List <double> [numNodes]; for (int i = 0; i < numNodes; i++) { edges[i] = new List <int>(); } //Add Edges for (int i = 0; i < numNodes - 1; i++) { for (int j = i + 1; j < numNodes; j++) { if (d[i, j] <= threshold) { edges[i].Add(j); edges[j].Add(i); } } } for (int i = 0; i < numNodes; i++) { nodes[i] = new LightWeightGraph.LightWeightNode(i, true, edges[i], weights[i]); } return(new LightWeightGraph(nodes, true)); }
public LightWeightGraph GetNormalizedRandomGraph(DistanceMatrix d) { int numNodes = d.Count; var nodes = new LightWeightGraph.LightWeightNode[numNodes]; // make an array to hold all possible edges, less the edges in the mst List <oneNode> myDistances = new List <oneNode>(); LightWeightGraph mst = LightWeightGraph.GetStackedMST(d, 1); LightWeightGraph.LightWeightNode[] mstNodes = mst.Nodes; //Create a list to hold edge values List <int>[] edges = new List <int> [numNodes]; List <double>[] weights = new List <double> [numNodes]; for (int i = 0; i < numNodes; i++) { edges[i] = new List <int>(); weights[i] = new List <double>(); } double largestMSTEdge = 0.0; // add edges from the mst to the edges list, to facilitate adding additional edges later on // Also find the largest edge to use as a cutoff for (int i = 0; i < numNodes; i++) { for (int j = 0; j < mstNodes[i].Edge.Length; j++) { largestMSTEdge = Math.Max(largestMSTEdge, mst[i].EdgeWeights[j]); edges[i].Add(mstNodes[i].Edge[j]); weights[i].Add(mstNodes[i].EdgeWeights[j]); } } largestMSTEdge *= _cutoffProp; // cycle through each possible edge // if the edge exists in the mst, continue // otherwise, add the edge to distances array, and add distance to the edge to the cummulative total for (int i = 0; i < numNodes - 1; i++) { for (int j = i + 1; j < numNodes; j++) { double dist = d[i, j]; if (dist >= largestMSTEdge || mstNodes[i].Edge.Contains(j)) { continue; } else { //Probability function goes here double addlProb = _normAlpha * (1.0 / Math.Exp(_xScale * dist / largestMSTEdge)); oneNode nd = new oneNode { prob = addlProb, fromNode = i, toNode = j, alreadyExists = false }; myDistances.Add(nd); } } } // walk through the array until you find the random number for (int m = 0; m < myDistances.Count; m++) { double rand = Utility.Util.Rng.NextDouble(); if (myDistances[m].prob > rand) { // we have found the edge to add. // add the edge if it does not already exist if (!myDistances[m].alreadyExists) { int from = myDistances[m].fromNode; int to = myDistances[m].toNode; double dist = d[from, to]; edges[from].Add(to); weights[from].Add(dist); edges[to].Add(from); weights[to].Add(dist); myDistances[m].alreadyExists = true; } } } for (int i = 0; i < numNodes; i++) { nodes[i] = new LightWeightGraph.LightWeightNode(i, true, edges[i], weights[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)); }
/// <summary> /// Creates a random graph, based on an mst. /// </summary> /// <param name="d">distance matrix used to construct the graph</param> /// <param name="alpha">the resulting average degree of the graph</param> /// /// <param name="expP">The probability of adding an edge depends on its distance: 1/d^expP</param> /// <returns></returns> public static LightWeightGraph GetRandomGraph(DistanceMatrix d, int alpha, double expP) { int numNodes = d.Count; var nodes = new LightWeightGraph.LightWeightNode[numNodes]; // make an array to hold all possible edges, less the edges in the mst oneNode[] myDistances = new oneNode[numNodes * (numNodes - 1) / 2 - (numNodes - 1)]; LightWeightGraph mst = LightWeightGraph.GetStackedMST(d, 1); LightWeightGraph.LightWeightNode[] mstNodes = mst.Nodes; int myDistancesIndex = 0; double myDistancesTotal = 0; //Create a list to hold edge values List <int>[] edges = new List <int> [numNodes]; List <double>[] weights = new List <double> [numNodes]; for (int i = 0; i < numNodes; i++) { edges[i] = new List <int>(); } // add edges from the mst to the edges list, to facilitate adding additional edges later on for (int i = 0; i < numNodes; i++) { for (int j = 0; j < mstNodes[i].Edge.Length; j++) { edges[i].Add(mstNodes[i].Edge[j]); } } // cycle through each possible edge // if the edge exists in the mst, continue // otherwise, add the edge to distances array, and add distance to the edge to the cummulative total for (int i = 0; i < numNodes - 1; i++) { for (int j = i + 1; j < numNodes; j++) { if (mstNodes[i].Edge.Contains(j)) { continue; } else { double addlProb = 1.0 / Math.Pow(d[i, j], expP); myDistancesTotal += addlProb; oneNode nd = new oneNode { prob = myDistancesTotal, fromNode = i, toNode = j, alreadyExists = false }; myDistances[myDistancesIndex] = nd; myDistancesIndex++; } } } // how many edges do we want to add? int desiredNewEdges = (alpha * numNodes) - (numNodes - 1); Random rnd = Utility.Util.Rng; // add edges randomly until we have added the desired number of edges while (desiredNewEdges > 0) { // generate a random number between 0 and myDistancesTotal double rand = rnd.NextDouble() * myDistancesTotal; // walk through the array until you find the random number for (int m = 0; m < myDistances.Length; m++) { if (myDistances[m].prob > rand) { // we have found the edge to add. // add the edge if it does not already exist if (!myDistances[m].alreadyExists) { edges[myDistances[m].fromNode].Add(myDistances[m].toNode); edges[myDistances[m].toNode].Add(myDistances[m].fromNode); myDistances[m].alreadyExists = true; desiredNewEdges--; break; } } } } for (int i = 0; i < numNodes; i++) { nodes[i] = new LightWeightGraph.LightWeightNode(i, true, edges[i], weights[i]); } return(new LightWeightGraph(nodes, true)); }