Генерация случайного кубического графика с универсальной вероятностью (или меньше)

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

Давайте назовем неориентированного графа без самокраев "кубическим", если каждая вершина имеет градус точно три. Учитывая положительное целое число N я хотел бы генерировать случайный кубический график на вершинах N. Я хотел бы за него иметь универсальную вероятность, то есть, если существуют кубические графики M на вершинах N вероятность генерации, каждый 1/М. Более слабое условие, которое прекрасно все еще, состоит в том, что каждый кубический график имеет ненулевую вероятность.

Я чувствую, что существует быстрый и умный способ сделать это, но до сих пор я был неудачен.

Я - плохой кодер, терпите этот ужасный код:

ПРЕД: края = (3*nodes)/2, узлы даже, константы выбраны таким способом, которым хеш работает (BIG_PRIME больше, чем края, SMALL_PRIME больше, чем узлы, LOAD_FACTOR является маленьким).

void random_cubic_graph() {

int i, j, k, count;
int *degree;
char guard;

count = 0;
degree = (int*) calloc(nodes, sizeof(int));

while (count < edges) {

    /* Try a new edge at random */

    guard = 0;
    i = rand() % nodes;
    j = rand() % nodes;

    /* Checks if it is a self-edge */

    if (i == j)
        guard = 1;

    /* Checks that the degrees are 3 or less */

    if (degree[i] > 2 || degree[j] > 2) 
        guard = 1;

    /* Checks that the edge was not already selected with an hash */

    k = 0;
    while(A[(j + k*BIG_PRIME) % (LOAD_FACTOR*edges)] != 0) {
        if (A[(j + k*BIG_PRIME) % (LOAD_FACTOR*edges)] % SMALL_PRIME == j)
            if ((A[(j + k*BIG_PRIME) % (LOAD_FACTOR*edges)] - j) / SMALL_PRIME == i)
                guard = 1;
        k++;
    }

    if (guard == 0)
        A[(j + k*BIG_PRIME) % (LOAD_FACTOR*edges)] = hash(i,j);

    k = 0;
    while(A[(i + k*BIG_PRIME) % (LOAD_FACTOR*edges)] != 0) {
        if (A[(i + k*BIG_PRIME) % (LOAD_FACTOR*edges)] % SMALL_PRIME == i)
            if ((A[(i + k*BIG_PRIME) % (LOAD_FACTOR*edges)] - i) / SMALL_PRIME == j)
                guard = 1;
        k++;
    }

    if (guard == 0) 
        A[(i + k*BIG_PRIME) % (LOAD_FACTOR*edges)] = hash(j,i);

    /* If all checks were passed, increment the count, print the edge, increment the degrees. */

    if (guard == 0) {
        count++;
        printf("%d\t%d\n", i, j);
        degree[i]++;
        degree[j]++;
    }

}

Проблема состоит в том, что ее заключительный край, который должен быть выбран, мог бы быть самокраем. Это происходит, когда N - 1 вершина уже имеет градус 3, только 1 имеет градус 1. Таким образом алгоритм не мог бы завершиться. Кроме того, я не полностью убежден, что вероятность универсальна.

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

9
задан Daniel Trebbien 24 June 2010 в 20:46
поделиться

3 ответа

Предположим, что N четное. (В противном случае не может быть кубического графа на N вершинах).

Вы можете сделать следующее:

Возьмите 3N точек и разделите их на N групп по 3 точки в каждой.

Теперь случайным образом объедините эти 3N точек в пары (примечание: 3N четные). т.е. женитесь на двух точках случайным образом и формируйте браки 3N / 2).

Если существует пара между группой i и группой j, создайте границу между i и j. Это дает граф на N вершинах.

Если эта случайная пара не создает кратных ребер или петель, у вас кубический граф.

Если нет, попробуйте еще раз. Это выполняется за ожидаемое линейное время и генерирует равномерное распределение.

Примечание: все кубические графы на N вершинах генерируются этим методом (в ответ на комментарии Хэмиша).

Чтобы увидеть это:

Пусть G - кубический граф с N вершинами.

Пусть вершины будут, 1, 2, ... N.

Пусть тремя соседями j будут A (j), B (j) и C (j).

Для каждого j постройте группу упорядоченных пар {(j, A (j)), (j, B (j)), (j, C (j))}.

Это дает нам 3N упорядоченных пар. Мы объединяем их в пары: (u, v) соединяется с (v, u).

Таким образом, любой кубический граф соответствует спариванию и наоборот ...

Более подробную информацию об этом алгоритме и более быстрых алгоритмах можно найти здесь: Быстрое создание случайных регулярных графов .

10
ответ дан 4 December 2019 в 15:11
поделиться

Предупреждение: в этом ответе я делаю много интуитивных, но, возможно, неправильных утверждений. Вам обязательно стоит их доказать, если вы собираетесь использовать эту идею.

Перечисление кубических графов

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

Вот моя стратегия перечисления кубических графов: выбрать первую вершину и перебрать все возможные варианты трех смежных вершин. Во время этих итераций выполняйте рекурсию на следующей вершине с предостережением, что вы должны отслеживать, сколько ребер необходимо для каждой степени вершины, чтобы достичь 3. Продолжайте таким же образом, пока не будет достигнут самый низкий уровень. Теперь у вас есть первый кубический граф. Отмените недавно добавленные ребра и переходите к следующей возможности, пока не останется ни одной. Есть несколько деталей реализации, которые вам необходимо рассмотреть, но в целом они просты.

Обобщите перечисление в качестве выбора

После того, как вы можете перечислить все элементы, сделать случайный выбор становится тривиальным делом. Например, вы можете просканировать список один раз, чтобы вычислить его размер, затем выбрать случайное число в [0, size), а затем снова просканировать последовательность, чтобы получить элемент с этим смещением. Это невероятно неэффективно, поскольку занимает как минимум время, пропорциональное количеству кубических графов O (n ^ 3), но это работает.

Пожертвовать равномерной вероятностью ради эффективности

Очевидное ускорение здесь состоит в том, чтобы делать случайный выбор ребер на каждом уровне вместо повторения каждой возможности.К сожалению, это предпочтение отдается некоторым графикам из-за того, как ваш ранний выбор влияет на доступность более поздних вариантов. Принимая во внимание необходимость отслеживать оставшиеся свободные вершины, вы должны быть в состоянии достичь O (n log n) времени и O (n) пространства. Значительно лучше, чем алгоритм подсчета.

...

Возможно, лучше. Наверное, намного лучше. Но это должно помочь вам начать.

2
ответ дан 4 December 2019 в 15:11
поделиться

Другим термином для кубического графа является 3-регулярный граф или трехвалентный граф.

Ваша задача требует уточнения, поскольку "количество кубических графов" может означать количество кубических графов на 2n узлах, которые неизоморфны друг другу, или количество (неизоморфных) кубических графов на 2n меченых узлах. Первое задается целочисленной последовательностью A005638, и, вероятно, нетривиальная задача - равномерно выбрать случайный класс изоморфизма кубических графов эффективным образом (т.е. не перечисляя их все, а затем выбирая один класс). Последняя задача решается по A002829.

В Википедии есть статья о случайных регулярных графах, на которую вам стоит взглянуть.

1
ответ дан 4 December 2019 в 15:11
поделиться
Другие вопросы по тегам:

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