определение точек от набора попарных расстояний

На вашей диаграмме рассмотрите значение x + y для каждой ячейки

diagram with X+Y for each cell

Для сортировки ячеек сверху вниз можно просто отсортировать по значению x+y.

6
задан mat kelcey 17 January 2010 в 10:48
поделиться

4 ответа

Вы на правильном пути с многомерным масштабированием (MDS), но MDS непрактичен для больших наборов данных, поскольку его временная сложность квадратична в числе очков. Можно хотеть посмотреть на FastMap, который имеет линейную временную сложность и лучше подходит для индексации. См.:

Christos Faloutsos и King-Ip Lin: "FastMap: Алгоритм FAST для Индексации, Анализа данных и Визуализации Традиционных и Мультимедийных Наборов данных, в материалах SIGMOD, 1995, doi:10.1145/223784.223812

6
ответ дан 8 December 2019 в 18:43
поделиться

Можно "обмануть" и использовать повторяющийся численный метод для этого. Возьмите все точки, чтобы быть в некоторых "случайных" положениях первоначально и затем цикле через них, отодвинув их друг от друга пропорционально к необходимому расстоянию. Это предпочтет, чтобы некоторые точки, но берущий в среднем перемещения прежде, чем применить их, затем применяя среднее число удалили эту проблему. Это - O (n ²) алгоритм, но очень простой реализовать и понять. В 2-м примере ниже ошибки <<10%, хотя это не может вести себя так хорошо, если данные расстояния нереалистичны.

Пример C++:

#include <conio.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>

#define DAMPING_FACTOR 0.99f

class point
{
public:
    float x;
    float y;
public:
    point() : x(0), y(0) {}
};

// symmetric matrix with distances
float matrix[5][5] =    {
                            { 0.0f, 4.5f, 1.5f, 2.0f, 4.0f },
                            { 4.5f, 0.0f, 4.0f, 3.0f, 3.5f },
                            { 1.5f, 4.0f, 0.0f, 1.0f, 5.0f },
                            { 2.0f, 3.0f, 1.0f, 0.0f, 4.5f },
                            { 4.0f, 3.5f, 5.0f, 4.5f, 0.0f }
                        };
int main(int argc, char** argv)
{
    point p[5];
    for(unsigned int i = 0; i < 5; ++i)
    {
        p[i].x = (float)(rand()%100)*0.1f;
        p[i].y = (float)(rand()%100)*0.1f;
    }

    // do 1000 iterations
    float dx = 0.0f, dy = 0.0f, d = 0.0f;
    float xmoves[5], ymoves[5];

    for(unsigned int c = 0; c < 1000; ++c)
    {
        for(unsigned int i = 0; i < 5; ++i) xmoves[i] = ymoves[i] = 0.0f;
        // iterate across each point x each point to work out the results of all of the constraints in the matrix
        // collect moves together which are slightly less than enough (DAMPING_FACTOR) to correct half the distance between each pair of points
        for(unsigned int i = 0; i < 5; ++i)
        for(unsigned int j = 0; j < 5; ++j)
        {
            if(i==j) continue;
            dx = p[i].x - p[j].x;
            dy = p[i].y - p[j].y;
            d = sqrt(dx*dx + dy*dy);
            dx /= d;
            dy /= d;
            d = (d - matrix[i][j])*DAMPING_FACTOR*0.5f*0.2f;

            xmoves[i] -= d*dx;
            ymoves[i] -= d*dy;

            xmoves[j] += d*dx;
            ymoves[j] += d*dy;
        }

        // apply all at once
        for(unsigned int i = 0; i < 5; ++i)
        {
            p[i].x += xmoves[i];
            p[i].y += ymoves[i];
        }
    }

    // output results
    printf("Result:\r\n");
    for(unsigned int i = 0; i < 5; ++i)
    {
        for(unsigned int j = 0; j < 5; ++j)
        {
            dx = p[i].x - p[j].x;
            dy = p[i].y - p[j].y;
            printf("%f ", sqrt(dx*dx + dy*dy));
        }
        printf("\r\n");
    }

    printf("\r\nDesired:\r\n");
    for(unsigned int i = 0; i < 5; ++i)
    {
        for(unsigned int j = 0; j < 5; ++j)
        {
            printf("%f ", matrix[i][j]);
        }
        printf("\r\n");
    }

    printf("Absolute difference:\r\n");
    for(unsigned int i = 0; i < 5; ++i)
    {
        for(unsigned int j = 0; j < 5; ++j)
        {
            dx = p[i].x - p[j].x;
            dy = p[i].y - p[j].y;
            printf("%f ", abs(sqrt(dx*dx + dy*dy) - matrix[i][j]));
        }
        printf("\r\n");
    }

    printf("Press any key to continue...");

    while(!_kbhit());

    return 0;
}
4
ответ дан 8 December 2019 в 18:43
поделиться

Существует алгоритм для того, чтобы сделать это в Программировании Коллективного разума, p. 49, "Просматривая Данные в Двух Размерах", которые могли быть адаптированы к n-размерам.

Эй - это - многомерное масштабирование - таким образом, я предполагаю, что Вы на правильном пути.

2
ответ дан 8 December 2019 в 18:43
поделиться

Я не могу отредактировать оригинал, потому что у меня нет достаточного количества представителя, но я попытался вновь заявить о проблеме здесь.

OP имеет вход матрица NxN расстояний. Он хочет создать выходной массив, размер N, N-мерных координат, представляющих точки, где расстояние между каждой точкой хранится во входной матрице.

Обратите внимание, что это не разрешимо в общем случае:

Предположим, что у меня есть матрица как это

   A  B  C  
A  x  1  2  
B     x  0  
C        x  

A является 1 единицей расстояния (скажите, что 1 метр), далеко от B, и A на расстоянии в один метр от C. Но B и C находятся в том же месте.

В данном случае минимальная сумма ошибок составляет 1 метр, и существует бесконечное множество решений, которые достигают того результата

1
ответ дан 8 December 2019 в 18:43
поделиться
Другие вопросы по тегам:

Похожие вопросы: