public void CalculateShortestPaths()
        {
            var currentVisitingVertix = VerticesList[0];

            while (currentVisitingVertix != null)
            {
                VisitedVertices.Add(currentVisitingVertix.Name);

                var adjacencyLinkedListCurrent = FindNextEdge(currentVisitingVertix.AdjacencyLinkedList.ReturnHead());

                while (adjacencyLinkedListCurrent != null)
                {
                    int distance;
                    int oldDistance;
                    ShortestPaths.TryGetValue(currentVisitingVertix.Name, out distance);
                    ShortestPaths.TryGetValue(adjacencyLinkedListCurrent.Name, out oldDistance);
                    var updateDistance = distance + adjacencyLinkedListCurrent.EdgeValue;
                    if (updateDistance < oldDistance)
                    {
                        ShortestPaths[adjacencyLinkedListCurrent.Name] = updateDistance;
                    }

                    adjacencyLinkedListCurrent = FindNextEdge(adjacencyLinkedListCurrent);
                }

                currentVisitingVertix = FindMinValueInShortestPaths();
            }
        }
Example #2
0
        /// <summary>
        /// This method calculate the number of bonds on the shortest path between two atoms.
        /// </summary>
        /// <param name="atom">The <see cref="IAtom"/> for which the <see cref="Result"/> is requested</param>
        /// <param name="focusPosition">The position of the focus atom</param>
        /// <returns>The number of bonds on the shortest path between two atoms</returns>
        public Result Calculate(IAtom atom, int focusPosition = 0)
        {
            var focus = container.Atoms[focusPosition];

            // could be cached
            var bondsToAtom = new ShortestPaths(container, atom).GetDistanceTo(focus);

            return(new Result(bondsToAtom));
        }
        private void ComputeOptimalSwitchingCosts()
        {
            var graph = this.ConstructFullGraph();

            // TODO: disable parallel computation for single-threaded programs?
            Parallel.ForEach(
                this.instance.Intervals,
                new ParallelOptions {
                MaxDegreeOfParallelism = -1
            },
                beginInterval =>
            {
                int beginStateIdx = beginInterval.Index <= 1 ? this.instance.BaseOffStateIdx : this.instance.OnStateIdx;

                var shortestPaths = new ShortestPaths(graph.NodesCount);
                shortestPaths.SetInput(
                    graph,
                    false,
                    false,
                    graph.NodeIndex(beginInterval.Index, beginStateIdx));
                if (shortestPaths.Solve(this.timer.RemainingTime).IsFeasibleSolution())
                {
                    for (int endIntervalIdx = beginInterval.Index;
                         endIntervalIdx <= this.instance.Intervals.Length;
                         endIntervalIdx++)
                    {
                        int endStateIdx = endIntervalIdx >= (this.instance.Intervals.Length - 1) ?
                                          this.instance.BaseOffStateIdx
                                : this.instance.OnStateIdx;

                        if (!this.FeasibilityCheck(beginInterval.Index, endIntervalIdx, beginStateIdx, endStateIdx))
                        {
                            continue;
                        }

                        int pathWeight = int.MaxValue;
                        if (endIntervalIdx == this.instance.Intervals.Length)
                        {
                            pathWeight = shortestPaths.PathWeights[graph.Sink];
                        }
                        else
                        {
                            pathWeight = shortestPaths.PathWeights[graph.NodeIndex(endIntervalIdx, endStateIdx)];
                        }

                        this.OptimalCosts[beginInterval.Index][endIntervalIdx] =
                            pathWeight == int.MaxValue ? (int?)null : pathWeight;
                    }
                }
            });
        }
Example #4
0
        private static bool MakeDescriptorLastStage(
            List <double> rdfProtonCalculatedValues,
            IAtom atom,
            IAtom clonedAtom,
            IAtomContainer mol,
            IAtom neighbour0,
            List <int> singles,
            List <int> doubles,
            List <int> atoms,
            List <int> bondsInCycloex)
        {
            ///////////////////////THE SECOND CALCULATED DESCRIPTOR IS g(H)r TOPOLOGICAL WITH SUM OF BOND LENGTHS

            if (atoms.Any())
            {
                const double limitInf      = 1.4;
                const double limitSup      = 4;
                const double smooth        = -20;
                var          startVertex   = clonedAtom;
                var          shortestPaths = new ShortestPaths(mol, startVertex);
                for (int c = 0; c < desc_length; c++)
                {
                    var    ghrt = limitInf + (limitSup - limitInf) * ((double)c / desc_length);
                    double sum  = 0;
                    for (int at = 0; at < atoms.Count; at++)
                    {
                        double distance  = 0;
                        var    thisAtom  = atoms[at];
                        var    position  = thisAtom;
                        var    endVertex = mol.Atoms[position];
                        var    atom2     = mol.Atoms[position];
                        var    path      = shortestPaths.GetPathTo(endVertex);
                        for (int i = 1; i < path.Length; i++)
                        {
                            distance += CalculateDistanceBetweenTwoAtoms(mol.Atoms[path[i - 1]], mol.Atoms[path[i]]);
                        }
                        var partial = atom2.Charge.Value * Math.Exp(smooth * Math.Pow(ghrt - distance, 2));
                        sum += partial;
                    }
                    rdfProtonCalculatedValues.Add(sum);
                    Debug.WriteLine($"RDF gr-topol distance prob.: {sum} at distance {ghrt}");
                }
                return(true);
            }
            else
            {
                return(false);
            }
        }
Example #5
0
    //   APSP    layout     stress
    public static Vector2[] Stress(Func <int[, ], Vector2[], IEnumerable <double> > Layout, SparseMatrix <bool> adjMatrix, StreamWriter file)
    {
        int n = adjMatrix.MaxIdx() + 1;

        Console.Error.WriteLine("vertices=" + n);
        Console.Error.WriteLine("edges=" + adjMatrix.Count());

        var positions = new Vector2[n];
        var rnd       = new Random();

        int[,] shortestPaths = ShortestPaths.Bacon(adjMatrix, n);

        var sw = new Stopwatch();

        //for (int k = 0; k < 25; k++)
        //{
        //    GC.Collect();

        // initialise positions
        positions[0] = new Vector2(0, 0);    // for majorization
        for (int i = 1; i < n; i++)
        {
            positions[i] = new Vector2(rnd.NextDouble(), rnd.NextDouble());
        }

        sw.Restart();

        int iteration = 0;

        foreach (double stress in Layout(shortestPaths, positions))
        {
            double time = sw.ElapsedMilliseconds;
            string info = iteration + " " + stress + " " + time;
            Console.Error.WriteLine(info);
            //Console.WriteLine(info);
            file.WriteLine(info);
            iteration += 1;
        }

        //    Console.Error.WriteLine("finished run " + (k + 1) + "\n");
        //    Console.WriteLine();
        //    file.WriteLine();
        //}

        return(positions);
    }
Example #6
0
        public void ComputeMinPaths(string rootNodeName)
        {
            Node   startNode = Nodes[rootNodeName];
            string currentNodeName;
            BinaryHeap <Path <string> > unusedPaths = new BinaryHeap <Path <string> >(BinaryHeapType.MIN);

            // create all possible paths first
            Dictionary <string, Path <string> > pathDict = new Dictionary <string, Path <string> >();

            ShortestPaths.Add(rootNodeName, pathDict);

            foreach (string name in Nodes.Keys)
            {
                Path <string> path;

                if (name.Equals(rootNodeName))
                {
                    path          = new Path <string>(new string[] { rootNodeName });
                    path.Distance = 0;
                }
                else
                {
                    path          = new Path <string>(new string[] { rootNodeName, name });
                    path.Distance = Int32.MaxValue;
                }

                pathDict.Add(name, path);
                unusedPaths.Add(path);
            }

            while (unusedPaths.Count > 0)
            {
                //get the destination node of the path with the smallest global distance
                currentNodeName = unusedPaths[0][unusedPaths[0].Count - 1];
                Path <string> currentPath = ShortestPaths[rootNodeName][currentNodeName];
                //get all neighboring nodes and calculate the distance
                foreach (NodeNeighbor neighbor in Nodes[currentNodeName].Neighbors)  // update all distance

                {
                    int           neighborDistance = neighbor.Distance;
                    Path <string> neighborPath     = ShortestPaths[rootNodeName][neighbor.Id];

                    int oldDistance = neighborPath.Distance;
                    int newDistance = currentPath.Distance + neighborDistance;

                    if (newDistance < oldDistance && newDistance >= 0)
                    {
                        //merge the two paths

                        neighborPath.Clear();
                        foreach (string name in currentPath)
                        {
                            neighborPath.Add(name);
                        }

                        neighborPath.Add(neighbor.Id);
                        neighborPath.Distance = newDistance;
                    }
                }
                unusedPaths.Remove(currentPath);
            }
        }
Example #7
0
        /// <summary>
        /// calculate the stabilization of orbitals when they contain deficiency of charge.
        /// </summary>
        /// <param name="atomContainer">the molecule to be considered</param>
        /// <param name="atom">IAtom for which effective atom StabilizationCharges factor should be calculated</param>
        /// <returns>stabilizationValue</returns>
        public static double CalculatePositive(IAtomContainer atomContainer, IAtom atom)
        {
            /* restrictions */
            //        if(atomContainer.GetConnectedSingleElectronsCount(atom) > 0 || atom.FormalCharge != 1){
            if (atom.FormalCharge != 1)
            {
                return(0.0);
            }

            // only must be generated all structures which stabilize the atom in question.
            StructureResonanceGenerator gRI = new StructureResonanceGenerator();
            var reactionList = gRI.Reactions.ToList();

            reactionList.Add(new HyperconjugationReaction());
            gRI.Reactions = reactionList;
            var resonanceS = gRI.GetStructures(atomContainer);
            var containerS = gRI.GetContainers(atomContainer);

            if (resonanceS.Count < 2) // meaning it was not find any resonance structure
            {
                return(0.0);
            }

            int positionStart = atomContainer.Atoms.IndexOf(atom);

            var result1   = new List <double>();
            var distance1 = new List <int>();

            resonanceS.RemoveAt(0);// the first is the initial structure
            foreach (var resonance in resonanceS)
            {
                if (resonance.Atoms.Count < 2) // resonance with only one atom donnot have resonance
                {
                    continue;
                }

                ShortestPaths shortestPaths = new ShortestPaths(resonance, resonance.Atoms[positionStart]);

                /* search positive charge */

                PiElectronegativity electronegativity = new PiElectronegativity();

                foreach (var atomP in resonance.Atoms)
                {
                    IAtom atomR = atomContainer.Atoms[resonance.Atoms.IndexOf(atomP)];
                    if (containerS[0].Contains(atomR))
                    {
                        electronegativity.MaxIterations = 6;
                        double result = electronegativity.CalculatePiElectronegativity(resonance, atomP);
                        result1.Add(result);

                        int dis = shortestPaths.GetDistanceTo(atomP);
                        distance1.Add(dis);
                    }
                }
            }
            /* logarithm */
            double value = 0.0;
            double sum   = 0.0;

            var itDist = distance1.GetEnumerator();

            foreach (var ee in result1)
            {
                double suM = ee;
                if (suM < 0)
                {
                    suM = -1 * suM;
                }
                itDist.MoveNext();
                sum += suM * Math.Pow(0.67, itDist.Current);
            }
            value = sum;

            return(value);
        }
Example #8
0
        /// <summary>
        /// Main method:
        /// </summary>
        public static void Main()
        {
            // Create a random graph with the given edge and node count
            RandomGraphGenerator randomGraph = new RandomGraphGenerator(0);

            randomGraph.NodeCount = 30;
            randomGraph.EdgeCount = 60;
            Graph graph = randomGraph.Generate();

            // Create an edgemap and assign random double weights to
            // the edges of the graph.
            IEdgeMap weightMap = graph.CreateEdgeMap();
            Random   random    = new Random(0);

            for (IEdgeCursor ec = graph.GetEdgeCursor(); ec.Ok; ec.Next())
            {
                Edge e = ec.Edge;
                weightMap.SetDouble(e, 100.0 * random.NextDouble());
            }

            // Calculate the shortest path from the first to the last node
            // within the graph
            if (!graph.Empty)
            {
                Node   from = graph.FirstNode;
                Node   to   = graph.LastNode;
                double sum  = 0.0;

                // The undirected case first, i.e. edges of the graph and the
                // resulting shortest path are considered to be undirected
                EdgeList path = ShortestPaths.SingleSourceSingleSink(graph, from, to, false, weightMap);
                for (IEdgeCursor ec = path.Edges(); ec.Ok; ec.Next())
                {
                    Edge   e      = ec.Edge;
                    double weight = weightMap.GetDouble(e);
                    Console.WriteLine(e + " weight = " + weight);
                    sum += weight;
                }
                if (sum == 0.0)
                {
                    Console.WriteLine("NO UNDIRECTED PATH");
                }
                else
                {
                    Console.WriteLine("UNDIRECTED PATH LENGTH = " + sum);
                }


                // Next the directed case, i.e. edges of the graph and the
                // resulting shortest path are considered to be directed.
                // Note that this shortest path can't be shorter then the one
                // for the undirected case

                path = ShortestPaths.SingleSourceSingleSink(graph, from, to, true, weightMap);
                sum  = 0.0;
                for (IEdgeCursor ec = path.Edges(); ec.Ok; ec.Next())
                {
                    Edge   e      = ec.Edge;
                    double weight = weightMap.GetDouble(e);
                    Console.WriteLine(e + " weight = " + weight);
                    sum += weight;
                }
                if (sum == 0.0)
                {
                    Console.WriteLine("NO DIRECTED PATH");
                }
                else
                {
                    Console.WriteLine("DIRECTED PATH LENGTH = " + sum);
                }


                Console.WriteLine("\nAuxiliary distance test\n");

                INodeMap distanceMap = graph.CreateNodeMap();
                INodeMap predMap     = graph.CreateNodeMap();
                ShortestPaths.SingleSource(graph, from, true, weightMap, distanceMap, predMap);
                if (distanceMap.GetDouble(to) == double.PositiveInfinity)
                {
                    Console.WriteLine("Distance from first to last node is infinite");
                }
                else
                {
                    Console.WriteLine("Distance from first to last node is " + distanceMap.GetDouble(to));
                }

                // Dispose distanceMap since it is not needed anymore
                graph.DisposeNodeMap(distanceMap);
            }

            // Dispose weightMap since it is not needed anymore
            graph.DisposeEdgeMap(weightMap);

            Console.WriteLine("\nPress key to end demo.");
            Console.ReadKey();
        }
	private void fillShortestPaths()
	{
		shortestPaths = new ShortestPaths ();
		List<Vector2> GSPlayerUnits = new List<Vector2>();
		foreach (Unit unit in map.getUnits (Game.EntityType.GS))
		{
			GSPlayerUnits.Add (unit.position);
		}

		foreach (Unit unit in map.getUnits (Game.EntityType.Blip))
		{
			GSPlayerUnits.Add (unit.position);
		}

		//Add Deployment area positions
		for (int i = 0; i < map.otherAreas.Length; i++)
		{
			bool posExists = false;
			foreach (Vector2 position in GSPlayerUnits)
			{
				if (position == new Vector2(-1 - i, 0))
				{
					posExists = true;
					break;
				}
			}
			if (!posExists)
			{
				GSPlayerUnits.Add (new Vector2(-1 - i, 0));
			}
		}

		foreach (Vector2 position in GSPlayerUnits)
		{
			shortestPaths.define (position);
		}

		//For each Space Marine, find which Genestealers it is closest to
		foreach (Unit SM in map.getUnits(Game.EntityType.SM))
		{
			foreach (Vector2 position in GSPlayerUnits)
			{
				Game.Facing facing = Game.Facing.North;
				//Test whether the unit is in a deployment area
				if (position.x < -0.1f)
				{
					if (map.otherAreas.Length > -1 - Mathf.RoundToInt (position.x))
					{
						facing = map.otherAreas[-1 - Mathf.RoundToInt (position.x)].relativePosition;
					}
				}

				//Find the shortest path between SM and GS
				Path testPath = getPath (position, facing, SM.position, facing, orthoSet(), true, true, true, true);
				Path currentPath = shortestPaths.get (position);
				if (currentPath != null && testPath != null)
				{
					if (testPath.APCost < currentPath.APCost)
					{
						shortestPaths.set(position, testPath);
					}
				}
				else
				{
					shortestPaths.set (position, testPath);
				}
			}
		}
	}
Example #10
0
    public static Vector2[] SparseSGD(SparseMatrix <bool> adjMatrix, int numPivots, int numIter)
    {
        var sw = new Stopwatch();

        sw.Start();

        int n = adjMatrix.MaxIdx() + 1;

        Console.Error.WriteLine("vertices=" + n);
        // create sparse distance matrix
        var d = new SparseMatrix <int>();
        Dictionary <int, List <int> > regions = ShortestPaths.SparseBacon(adjMatrix, d, 1, numPivots);

        var w = new SparseMatrix <double>();

        //////////////
        // 1-stress //
        //////////////

        var constraints = new List <Tuple <int, int> >();

        foreach (var ij in adjMatrix.IndexPairs)
        {
            int i = ij.Item1, j = ij.Item2;
            if (i > j)
            {
                constraints.Add(ij);
                d[i, j] = d[j, i] = 1;
                w[i, j] = w[j, i] = 1.0;
            }
        }
        Console.Error.WriteLine("edges=" + constraints.Count);

        ///////////////////
        // sparse stress //
        ///////////////////

        // for every pivot
        foreach (int pivot in regions.Keys)
        {
            // calculate the number of vertices in the region at each distance
            var regionDistances = new Dictionary <int, int>();
            int maxDistance     = 0;
            foreach (int regionMember in regions[pivot])
            {
                if (regionMember != pivot)
                {
                    int distance = d[pivot, regionMember];
                    maxDistance = Math.Max(distance, maxDistance);
                    if (!regionDistances.ContainsKey(distance))
                    {
                        regionDistances[distance] = 1;
                    }
                    else
                    {
                        regionDistances[distance] += 1;
                    }
                }
            }
            var cumulDistances = new List <int>();
            cumulDistances.Add(1);
            for (int i = 1; i <= maxDistance; i++)
            {
                cumulDistances.Add(cumulDistances[i - 1] + regionDistances[i]);
            }
            var terms = new List <int>();
            // for every other vertex
            for (int thisVertex = 0; thisVertex < n; thisVertex++)
            {
                int distance = d[pivot, thisVertex];

                // cut out paths to itself and its direct neighbours
                if (thisVertex != pivot && distance > 1)
                {
                    int s = regions[pivot].Count;
                    if (distance / 2 < cumulDistances.Count - 1)
                    {
                        s = cumulDistances[distance / 2];
                    }

                    double weight = 1f / (distance * distance);
                    //double w_pi = weight * numPivots / terms.Count;
                    double w_ip = weight * s;

                    d[pivot, thisVertex] = d[thisVertex, pivot] = distance;
                    w[thisVertex, pivot] = w_ip;
                }
            }
        }

        foreach (var ij in d.IndexPairs)
        {
            int i = ij.Item1, j = ij.Item2;
            if (i < j)
            {
                constraints.Add(ij);
            }
        }
        Console.Error.WriteLine("constraints=" + constraints.Count);

        // initialise positions
        var positions = new Vector2[n];
        var rnd       = new Random();

        for (int i = 0; i < n; i++)
        {
            positions[i] = new Vector2(rnd.NextDouble(), rnd.NextDouble());
        }


        // calculate annealing
        double wMax = 0, wMin = double.MaxValue;

        foreach (var w_ij in w)
        {
            wMax = w_ij > wMax ? w_ij : wMax;
            wMin = w_ij < wMin ? w_ij : wMin;
        }
        double cMax = 1 / wMin;
        double cMin = 0.1 / wMax;

        double lambda = Math.Log(cMin / cMax) / (numIter - 1);

        Console.Error.WriteLine("cMax=" + cMax + " cMin=" + cMin + " rate=" + lambda);

        // SGD
        for (int k = 0; k < numIter + 5; k++)
        {
            FYShuffle(constraints, rnd);
            double c = cMax * Math.Exp(lambda * k);

            foreach (var ij in constraints)
            {
                int i = ij.Item1, j = ij.Item2;

                Vector2 pq = positions[i] - positions[j];
                // mag is |p-q|
                double mag = pq.Magnitude();
                // r is minimum distance each vertex has to move to satisfy the constraint
                double r = (d[i, j] - mag) / 2;

                // the weighting for i and j are different
                double wc = w[i, j] * c;
                wc = Math.Min(wc, 1);
                double r_i = wc * r;

                wc = w[j, i] * c;
                wc = Math.Min(wc, 1);
                double r_j = wc * r;

                positions[i] += pq * (r_i / mag);
                positions[j] -= pq * (r_j / mag);
            }
            Console.Error.Write(k);
        }
        Console.Error.WriteLine("done!");

        Console.Error.WriteLine("time=" + sw.ElapsedMilliseconds + "ms");
        return(positions);
    }
Example #11
0
    public static Vector2[] SparseMajorization(SparseMatrix <bool> adjMatrix, int numPivots, int numIter)
    {
        var sw = new Stopwatch();

        sw.Start();

        int n = adjMatrix.MaxIdx() + 1;

        Console.Error.WriteLine("vertices=" + n);
        // create sparse distance matrix
        var d = new SparseMatrix <int>();
        Dictionary <int, List <int> > regions = ShortestPaths.SparseBacon(adjMatrix, d, 1, numPivots);

        var w = new SparseMatrix <double>();

        //////////////
        // 1-stress //
        //////////////

        foreach (var ij in adjMatrix.IndexPairs)
        {
            int i = ij.Item1, j = ij.Item2;
            if (i > j)
            {
                d[i, j] = d[j, i] = 1;
                w[i, j] = w[j, i] = 1.0;
            }
        }

        ///////////////////
        // sparse stress //
        ///////////////////

        // for every pivot
        foreach (int pivot in regions.Keys)
        {
            // calculate the number of vertices in the region at each distance
            var regionDistances = new Dictionary <int, int>();
            int maxDistance     = 0;
            foreach (int regionMember in regions[pivot])
            {
                if (regionMember != pivot)
                {
                    int distance = d[pivot, regionMember];
                    maxDistance = Math.Max(distance, maxDistance);
                    if (!regionDistances.ContainsKey(distance))
                    {
                        regionDistances[distance] = 1;
                    }
                    else
                    {
                        regionDistances[distance] += 1;
                    }
                }
            }
            var cumulDistances = new List <int>();
            cumulDistances.Add(1);
            for (int i = 1; i <= maxDistance; i++)
            {
                cumulDistances.Add(cumulDistances[i - 1] + regionDistances[i]);
            }
            var terms = new List <int>();
            // for every other vertex
            for (int thisVertex = 0; thisVertex < n; thisVertex++)
            {
                int distance = d[pivot, thisVertex];

                // cut out paths to itself and its direct neighbours
                if (thisVertex != pivot && distance > 1)
                {
                    int s = regions[pivot].Count;
                    if (distance / 2 < cumulDistances.Count - 1)
                    {
                        s = cumulDistances[distance / 2];
                    }

                    double weight = 1f / (distance * distance);
                    //double w_pi = weight * numPivots / terms.Count;
                    double w_ip = weight * s;

                    d[pivot, thisVertex] = d[thisVertex, pivot] = distance;
                    w[thisVertex, pivot] = w_ip;
                }
            }
        }

        // initialise positions
        var X   = new Vector2[n];
        var rnd = new Random();

        for (int i = 0; i < n; i++)
        {
            X[i] = new Vector2(rnd.NextDouble(), rnd.NextDouble());
        }

        var wBot = new Dictionary <int, double>();

        foreach (int i in adjMatrix.GetRowIndices())
        {
            double bot = 0;
            foreach (int j in adjMatrix.GetColumnIndicesInRow(i))
            {
                if (i != j)
                {
                    bot += w[i, j];
                }
            }
            foreach (int p in regions.Keys)
            {
                if (p != i && adjMatrix[i, p] == false)
                {
                    bot += w[i, p];
                }
            }
            wBot[i] = bot;
        }


        for (int k = 0; k < numIter; k++)
        {
            foreach (int i in adjMatrix.GetRowIndices())
            {
                double xTop = 0, yTop = 0;
                // do neighbours
                foreach (int j in adjMatrix.GetColumnIndicesInRow(i))
                {
                    if (i != j)
                    {
                        double dist = (X[i] - X[j]).Magnitude();
                        xTop += w[i, j] * (X[j].x + (d[i, j] * (X[i].x - X[j].x)) / dist);
                        yTop += w[i, j] * (X[j].y + (d[i, j] * (X[i].y - X[j].y)) / dist);
                    }
                }
                // do pivots
                foreach (int p in regions.Keys)
                {
                    if (p != i && adjMatrix[i, p] == false)
                    {
                        double w_ip = w[i, p];
                        double dist = (X[i] - X[p]).Magnitude();
                        xTop += w[i, p] * (X[p].x + (d[i, p] * (X[i].x - X[p].x)) / dist);
                        yTop += w[i, p] * (X[p].y + (d[i, p] * (X[i].y - X[p].y)) / dist);
                    }
                }
                X[i] = new Vector2(xTop / wBot[i], yTop / wBot[i]);
            }
            Console.Error.Write(k);
        }

        Console.Error.WriteLine("done!");

        Console.Error.WriteLine("time=" + sw.ElapsedMilliseconds + "ms");
        return(X);
    }