//Threshold based
        public static LightWeightGraph GetGeometricGraph(DistanceMatrix distances, double threshold)
        {
            //construct the geo graph
            int numNodes = distances.Count;
            var nodes    = new LightWeightNode[numNodes];

            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 (distances[i, j] <= threshold)
                    {
                        edges[i].Add(j);
                        edges[j].Add(i);
                    }
                }
            }
            for (int i = 0; i < numNodes; i++)
            {
                nodes[i] = new LightWeightNode(i, true, edges[i], weights[i]);
            }

            return(new LightWeightGraph(nodes, true));
        }
Пример #2
0
 public LightWeightGraph()
 {
     Nodes      = new LightWeightNode[1];
     NumNodes   = 1;
     Nodes[0]   = new LightWeightNode(0, false, new List <int>());
     IsWeighted = false;
 }
 /// <summary>
 /// Copy Constructor
 /// </summary>
 /// <param name="n">LightWeightNode to copy</param>
 public LightWeightNode(LightWeightNode n)
 {
     Id          = n.Id;
     Label       = n.Label;
     Edge        = (int[])n.Edge.Clone();
     EdgeWeights = (double[])n.EdgeWeights.Clone();
     //NodeWeight = n.NodeWeight;
     Count = n.Count;
 }
        public static LWGWithNodeDescriptors GetGraphFromNetFile(String file)
        {
            using (StreamReader sr = new StreamReader(file))
            {
                String vertCountPattern = "[*]Vertices\\s+(?<vert>\\d+)";
                String firstLine        = sr.ReadLine();
                var    match            = Regex.Match(firstLine, vertCountPattern, RegexOptions.IgnoreCase);
                int    numVert          = int.Parse(match.Groups["vert"].Value);

                String vertPattern =
                    "\\s+(?<vertid>\\d+)\\s+\"(?<vertName>[^\"]+)\"\\s+(?<x>\\d[.]\\d+)\\s+(?<y>\\d+[.]\\d+)";

                NetVertDesciption[] verts = new NetVertDesciption[numVert];
                for (int i = 0; i < numVert; i++)
                {
                    String line = sr.ReadLine();
                    match = Regex.Match(line, vertPattern, RegexOptions.IgnoreCase);
                    String vertID   = match.Groups["vertid"].Value;
                    String vertName = match.Groups["vertName"].Value;
                    String x        = match.Groups["x"].Value;
                    String y        = match.Groups["y"].Value;
                    verts[i] = (new NetVertDesciption(int.Parse(vertID) - 1, vertName, double.Parse(x), double.Parse(y)));
                }

                while (!sr.ReadLine().Contains("*Edges"))
                {
                }

                List <int>[]    edges       = new List <int> [numVert];
                List <double>[] edgeWeights = new List <double> [numVert];
                for (int i = 0; i < numVert; i++)
                {
                    edges[i]       = new List <int>();
                    edgeWeights[i] = new List <double>();
                }
                String edgePattern =
                    "\\s+(?<fIndex>\\d+)\\s+(?<tIndex>\\d+)\\s+(?<dist>\\d[.]\\d+)";
                while (!sr.EndOfStream)
                {
                    String line = sr.ReadLine();
                    match = Regex.Match(line, edgePattern, RegexOptions.IgnoreCase);
                    int    from = int.Parse(match.Groups["fIndex"].Value) - 1;
                    int    to   = int.Parse(match.Groups["tIndex"].Value) - 1;
                    double dist = double.Parse(match.Groups["dist"].Value);
                    edges[from].Add(to); edgeWeights[from].Add(dist);
                    edges[to].Add(from); edgeWeights[to].Add(dist);
                }

                LightWeightNode[] nodes = new LightWeightNode[numVert];
                for (int i = 0; i < numVert; i++)
                {
                    nodes[i] = (new LightWeightNode(i, true, edges[i], edgeWeights[i]));
                }
                return(new LWGWithNodeDescriptors(verts, new LightWeightGraph(nodes, true)));
            }
        }
 /// <summary>
 /// Make a deep Copy of a Graph
 /// </summary>
 /// <param name="g">LightWeightGraph to copy</param>
 public LightWeightGraph(LightWeightGraph g)
     : base(DataType.Graph)
 {
     NumNodes = g.NumNodes;
     Nodes    = new LightWeightNode[NumNodes];
     for (int i = 0; i < NumNodes; i++)
     {
         Nodes[i] = new LightWeightNode(g[i]);
     }
     IsWeighted = g.IsWeighted;
 }
            //override for the sake of dictionary
            public override bool Equals(Object obj)
            {
                LightWeightNode n = obj as LightWeightNode;

                if (n == null)
                {
                    return(false);
                }

                return(n.Id == Id);
            }
        public static LightWeightGraph GetGraphFromFile(String file)
        {
            DelimitedFile parsedFile         = new DelimitedFile(file, false, true);
            int           parsedFileRowCount = parsedFile.Data.Count;

            //Ensure it has atleast 1 point and lists if it is weighted
            if (parsedFileRowCount < 2)
            {
                throw new InvalidDataException("file");
            }

            String weightString = parsedFile.Data[0][0];
            bool   isWeighted   = true;

            if (weightString == "unweighted")
            {
                isWeighted = false;
            }
            else if (weightString != "weighted")
            {
                throw new InvalidDataException("Invalid Weight Type");
            }


            //Start parsing the file
            List <List <NodeWeightPair> > nodes = new List <List <NodeWeightPair> >();

            for (int i = 1; i < parsedFileRowCount; i++)
            {
                var row = parsedFile.Data[i];

                List <NodeWeightPair> nList = new List <NodeWeightPair>();
                nodes.Add(nList);

                int edgeSize = (isWeighted) ? 2 : 1;
                for (int j = 1; j < row.Length; j += edgeSize)
                {
                    int    from   = int.Parse(row[j]);
                    double weight = (isWeighted) ? double.Parse(row[j + 1]) : 1.0f;
                    nList.Add(new NodeWeightPair {
                        Node = from, Weight = weight
                    });
                }
            }

            //Construct the graph
            var lwn = new LightWeightNode[nodes.Count];

            List <int>[]    edges       = new List <int> [nodes.Count];
            List <double>[] edgeWeights = new List <double> [nodes.Count];
            for (int i = 0; i < nodes.Count; i++)
            {
                edges[i]       = new List <int>();
                edgeWeights[i] = new List <double>();
            }

            for (int i = 0; i < lwn.Length; i++)
            {
                int count = nodes[i].Count;
                for (int j = 0; j < count; j++)
                {
                    var a = nodes[i][j];
                    edges[i].Add(a.Node);
                    edgeWeights[i].Add(a.Weight);
                }
            }

            for (int i = 0; i < lwn.Length; i++)
            {
                lwn[i] = new LightWeightNode(i, true, edges[i], edgeWeights[i]);
            }

            return(new LightWeightGraph(lwn, isWeighted));
        }
        //construct a subgraph using some exclusion rules
        public LightWeightGraph(LightWeightGraph lwg, bool[] S)
            : base(DataType.Graph)
        {
            int sSize = S.Count(c => c);

            //Setup our node array to be filled
            Nodes      = new LightWeightNode[lwg.NumNodes - sSize];
            NumNodes   = Nodes.Length;
            IsWeighted = lwg.IsWeighted;

            int nodeID = 0;

            int[] oldIDToNewID = new int[lwg.NumNodes];
            int[] oldLabel     = new int[NumNodes];
            //Now we need to itterate over each node in lwg
            for (int v = 0; v < lwg.NumNodes; v++)
            {
                if (!S[v])
                {
                    oldIDToNewID[v]  = nodeID;
                    oldLabel[nodeID] = lwg.Nodes[v].Label;
                    nodeID++;
                }
            }

            List <int>[]    edgesList      = new List <int> [NumNodes];
            List <double>[] edgeWeightList = new List <double> [NumNodes];
            for (int i = 0; i < lwg.NumNodes - sSize; i++)
            {
                edgesList[i]      = new List <int>();
                edgeWeightList[i] = new List <double>();
            }

            //now we should add our edges
            nodeID = 0;
            for (int v = 0; v < lwg.NumNodes; v++)
            {
                if (!S[v]) //if this is not a removed node we should add the edges
                {
                    var edges       = lwg.Nodes[v].Edge;
                    var edgeWeights = lwg.Nodes[v].EdgeWeights;
                    //Go through all of the edges and only add those not removed
                    for (int u = 0; u < lwg.Nodes[v].Count; u++)
                    {
                        int edgeTo = edges[u];
                        if (!S[edgeTo]) //this edge is still valid so we should add it
                        {
                            edgesList[nodeID].Add(oldIDToNewID[edgeTo]);
                            if (lwg.IsWeighted)
                            {
                                edgeWeightList[nodeID].Add(edgeWeights[u]);
                            }
                        }
                    }
                    nodeID++;
                }
            }

            for (int i = 0; i < NumNodes; i++)
            {
                Nodes[i] = new LightWeightNode(i, oldLabel[i], lwg.IsWeighted, edgesList[i], (IsWeighted) ? edgeWeightList[i] : null);
            }
        }
        //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));
        }
        //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));
        }