Exemple #1
0
    public static IEnumerable <double> Alternating(int[,] d, Vector2[] positions, IEnumerable <double> eta)
    {
        int n  = positions.Length;
        int nn = (n * (n - 1)) / 2;


        int[,] pairs1 = CreatePairs(n), pairs2 = CreatePairs(n);
        var rnd = new Random();

        GraphIO.FYShuffle2(pairs1, rnd);
        GraphIO.FYShuffle2(pairs2, rnd);

        // relax
        int k = 0;

        foreach (double c in eta)
        {
            int[,] pairs = k++ % 2 == 0 ? pairs1 : pairs2;
            for (int ij = 0; ij < nn; ij++)
            {
                int i = pairs[ij, 0], j = pairs[ij, 1];
                Satisfy(ref positions[i], ref positions[j], d[i, j], c);
            }

            yield return(GraphIO.CalculateStress(d, positions, n));
        }
    }
Exemple #2
0
    public static IEnumerable <double> Modulo(int[,] d, Vector2[] positions, IEnumerable <double> eta)
    {
        int n  = positions.Length;
        int nn = (n * (n - 1)) / 2;

        // relax

        int prime = 646957;

        int[] primitives = new int[] { 5, 6, 7, 17, 18, 20, 21, 24, 26, 28, 45, 46, 50, 53, 55, 58, 66, 68, 72, 73 };

        int k = 0;

        foreach (double c in eta)
        {
            int primitive = primitives[k++];
            int modulo    = 1;
            for (int ij = 0; ij < prime; ij++)
            {
                modulo = (modulo * primitive) % prime;
                if (modulo > nn)
                {
                    continue;
                }

                int idx = modulo - 1;
                int i   = (int)((1 + Math.Sqrt(8 * idx + 1)) / 2);
                int j   = idx - (i * (i - 1)) / 2;

                Satisfy(ref positions[i], ref positions[j], d[i, j], c);
            }
            yield return(GraphIO.CalculateStress(d, positions, n));
        }
    }
Exemple #3
0
    public static IEnumerable <double> Indices(int[,] d, Vector2[] positions, IEnumerable <double> eta)
    {
        int n = positions.Length;

        var indices = new int[n];

        for (int i = 0; i < n; i++)
        {
            indices[i] = i;
        }
        var rnd = new Random();

        //GraphIO.FYShuffle(indices, rnd);

        // relax
        foreach (double c in eta)
        {
            GraphIO.FYShuffle(indices, rnd);
            for (int i = 0; i < n; i++)
            {
                for (int j = 0; j < i; j++)
                {
                    Satisfy(ref positions[indices[i]], ref positions[indices[j]], d[indices[i], indices[j]], c);
                }
            }

            yield return(GraphIO.CalculateStress(d, positions, n));
        }
    }
Exemple #4
0
    public static IEnumerable <double> Momentum(int[,] d, Vector2[] X, double eta = .1, double beta = .9, int numIterations = 15)
    {
        int n = X.Length;

        // relax
        for (int k = 0; k < numIterations; k++)
        {
            var gradients = new Vector2[n];
            var momentums = new Vector2[n];
            for (int i = 0; i < n; i++)
            {
                for (int j = 0; j < i; j++)
                {
                    Vector2 gradient = Gradient(X[i], X[j], d[i, j]);

                    gradients[i] += gradient;
                    gradients[j] -= gradient;
                }
            }
            for (int i = 0; i < n; i++)
            {
                momentums[i] = momentums[i] * beta + gradients[i] * eta;
                X[i]        += momentums[i];
            }

            double stress = GraphIO.CalculateStress(d, X, n);
            yield return(stress);
        }
    }
Exemple #5
0
    public static IEnumerable <double> Convergence(int[,] d, Vector2[] positions, int expIter = 30, double eps = 0.03)
    {
        int n  = positions.Length;
        int nn = (n * (n - 1)) / 2;

        var pairs = CreatePairs(n);
        var rnd   = new Random();

        double etaMax = EtaMax(d), etaMin = .1;
        double lambda = -Math.Log(etaMin / etaMax) / (expIter - 1);

        double tSwitch = Math.Log(etaMax) / lambda;
        int    kSwitch = (int)tSwitch + 1;

        Console.Error.WriteLine(etaMax + " " + lambda + " " + tSwitch);

        for (int k = 0; k < kSwitch; k++)
        {
            GraphIO.FYShuffle2(pairs, rnd);
            double eta = etaMax * Math.Exp(-lambda * k);
            for (int ij = 0; ij < nn; ij++)
            {
                int i = pairs[ij, 0], j = pairs[ij, 1];
                Satisfy(ref positions[i], ref positions[j], d[i, j], eta);
            }
            //Console.Error.WriteLine("                  " + eta);
            double stress = GraphIO.CalculateStress(d, positions, n);
            yield return(stress);
        }

        for (int k = kSwitch; k < 1000; k++)
        {
            double maxMovement = 0;
            GraphIO.FYShuffle2(pairs, rnd);
            double eta = 1.0 / (1 + lambda * (k - tSwitch));
            for (int ij = 0; ij < nn; ij++)
            {
                int    i = pairs[ij, 0], j = pairs[ij, 1];
                double r = Satisfy(ref positions[i], ref positions[j], d[i, j], eta);

                r = Math.Abs(r);
                //r = r * r;
                if (r > maxMovement)
                {
                    maxMovement = r;
                }
            }
            //Console.Error.WriteLine("                  " + eta + " " + maxMovement);

            double stress = GraphIO.CalculateStress(d, positions, n);
            yield return(stress);

            if (maxMovement < eps)
            {
                yield break;
            }
        }
    }
Exemple #6
0
    public static IEnumerable <double> NoRand(int[,] d, Vector2[] positions, IEnumerable <double> eta)
    {
        int n = positions.Length;

        // relax
        foreach (double c in eta)
        {
            for (int i = 0; i < n; i++)
            {
                for (int j = 0; j < i; j++)
                {
                    Satisfy(ref positions[i], ref positions[j], d[i, j], c);
                }
            }

            yield return(GraphIO.CalculateStress(d, positions, n));
        }
    }
Exemple #7
0
    public static IEnumerable <double> Local(int[,] d, Vector2[] positions, double eps = 0.0001, int maxIter = 100)
    {
        int n = positions.Length;

        double prevStress = GraphIO.CalculateStress(d, positions, n);

        // majorize
        for (int k = 0; k < maxIter; k++)
        {
            for (int i = 0; i < n; i++)
            {
                double topSumX = 0, topSumY = 0, botSum = 0;
                for (int j = 0; j < n; j++)
                {
                    if (i != j)
                    {
                        double d_ij      = d[i, j];
                        double w_ij      = 1 / (d_ij * d_ij);
                        double magnitude = (positions[i] - positions[j]).Magnitude();

                        topSumX += w_ij * (positions[j].x + d_ij * (positions[i].x - positions[j].x) / (magnitude));
                        topSumY += w_ij * (positions[j].y + d_ij * (positions[i].y - positions[j].y) / (magnitude));
                        botSum  += w_ij;
                    }
                }

                double newX = topSumX / botSum;
                double newY = topSumY / botSum;
                positions[i] = new Vector2(newX, newY);
            }

            double stress = GraphIO.CalculateStress(d, positions, n);
            yield return(stress);

            if ((prevStress - stress) / prevStress < eps)
            {
                yield break;
            }
            prevStress = stress;
        }
    }
Exemple #8
0
    public static IEnumerable <double> Full(int[,] d, Vector2[] positions, IEnumerable <double> eta)
    {
        int n  = positions.Length;
        int nn = (n * (n - 1)) / 2;

        var pairs = CreatePairs(n);
        var rnd   = new Random();

        // relax
        foreach (double c in eta)
        {
            GraphIO.FYShuffle2(pairs, rnd);
            for (int ij = 0; ij < nn; ij++)
            {
                int i = pairs[ij, 0], j = pairs[ij, 1];
                Satisfy(ref positions[i], ref positions[j], d[i, j], c);
            }
            double stress = GraphIO.CalculateStress(d, positions, n);
            yield return(stress);
        }
    }
Exemple #9
0
    public static IEnumerable <double> EveryPair(int[,] d, Vector2[] positions, IEnumerable <double> eta)
    {
        int n   = positions.Length;
        int nn  = (n * (n - 1)) / 2;
        var rnd = new Random();

        //var indices = CreatePairs(n);

        // relax
        foreach (double c in eta)
        {
            for (int ij = 0; ij < nn; ij++)
            {
                int idx = rnd.Next(nn);
                int i   = (int)((1 + Math.Sqrt(8 * idx + 1)) / 2);
                int j   = idx - (i * (i - 1)) / 2;
                //int i = indices[idx, 0], j = indices[idx, 1];

                Satisfy(ref positions[i], ref positions[j], d[i, j], c);
            }
            yield return(GraphIO.CalculateStress(d, positions, n));
        }
    }
Exemple #10
0
    public static IEnumerable <double> Conj(int[,] d, Vector2[] positions, double eps = 0.0001, int maxIter = 1000)
    {
        int n = positions.Length;

        // first find the laplacian for the left hand side
        var laplacian_w = new double[n, n];

        Majorization.WeightLaplacian(d, laplacian_w, n);

        // cut out the first row and column
        var Lw = new double[n - 1, n - 1];

        for (int i = 1; i < n; i++)
        {
            for (int j = 1; j < n; j++)
            {
                Lw[i - 1, j - 1] = laplacian_w[i, j];
            }
        }

        // delta = w_ij * d_ij as in Majorization, Gansner et al.
        var deltas = new double[n, n];

        for (int i = 0; i < n; i++)
        {
            for (int j = 0; j < n; j++)
            {
                double dist = d[i, j];
                deltas[i, j] = 1.0 / dist;
            }
        }

        var LXt    = new double[n, n];  // the laplacian for the right hand side
        var LXt_Xt = new double[n - 1]; // skip the first position as it's fixed to (0,0)
        var Xt1    = new double[n - 1]; // X(t+1)

        // temporary variables to speed up conjugate gradient
        var r  = new double[n - 1];
        var p  = new double[n - 1];
        var Ap = new double[n - 1];

        double prevStress = GraphIO.CalculateStress(d, positions, n);

        // majorize
        for (int k = 0; k < maxIter; k++)
        {
            PositionLaplacian(deltas, positions, LXt, n);

            // solve for x axis
            Multiply_x(LXt, positions, LXt_Xt);
            ConjugateGradient.Cg(Lw, Xt1, LXt_Xt, r, p, Ap, .1, 10);
            for (int i = 1; i < n; i++)
            {
                positions[i].x = Xt1[i - 1];
            }

            // solve for y axis
            Multiply_y(LXt, positions, LXt_Xt);
            ConjugateGradient.Cg(Lw, Xt1, LXt_Xt, r, p, Ap, .1, 10);
            for (int i = 1; i < n; i++)
            {
                positions[i].y = Xt1[i - 1];
            }

            double stress = GraphIO.CalculateStress(d, positions, n);
            yield return(stress);

            if ((prevStress - stress) / prevStress < eps)
            {
                yield break;
            }
            prevStress = stress;
        }
    }
Exemple #11
0
    public static IEnumerable <double> Chol(int[,] d, Vector2[] positions, double eps = 0.0001, int maxIter = 1000)
    {
        int n = positions.Length;

        // first find the laplacian for the left hand side
        var laplacian_w = new double[n, n];

        WeightLaplacian(d, laplacian_w, n);

        // cut out the first row and column
        var cholesky_Lw = new double[n - 1, n - 1];

        for (int i = 1; i < n; i++)
        {
            for (int j = 1; j < n; j++)
            {
                cholesky_Lw[i - 1, j - 1] = laplacian_w[i, j];
            }
        }
        // p used to store diagonal values, as in Numerical Recipes
        var cholesky_p = new double[n - 1];

        Cholesky.Choldc(cholesky_Lw, cholesky_p);

        // delta = w_ij * d_ij as in Majorization, Gansner et al.
        var deltas = new double[n, n];

        for (int i = 0; i < n; i++)
        {
            for (int j = 0; j < n; j++)
            {
                double dist = d[i, j];
                deltas[i, j] = 1.0 / dist;
            }
        }

        var LXt    = new double[n, n];  // the laplacian for the right hand side
        var LXt_Xt = new double[n - 1]; // skip the first position as it's fixed to (0,0)
        var Xt1    = new double[n - 1]; // X(t+1)

        double prevStress = GraphIO.CalculateStress(d, positions, n);

        // majorize
        for (int k = 0; k < maxIter; k++)
        {
            PositionLaplacian(deltas, positions, LXt, n);

            // solve for x axis
            Multiply_x(LXt, positions, LXt_Xt);
            Cholesky.BackSubstitution(cholesky_Lw, cholesky_p, LXt_Xt, Xt1);
            for (int i = 1; i < n; i++)
            {
                positions[i].x = Xt1[i - 1];
            }

            // solve for y axis
            Multiply_y(LXt, positions, LXt_Xt);
            Cholesky.BackSubstitution(cholesky_Lw, cholesky_p, LXt_Xt, Xt1);
            for (int i = 1; i < n; i++)
            {
                positions[i].y = Xt1[i - 1];
            }

            double stress = GraphIO.CalculateStress(d, positions, n);
            yield return(stress);

            if ((prevStress - stress) / prevStress < eps)
            {
                yield break;
            }
            prevStress = stress;
        }
    }