Рассчитать количество топологий на {1,2,…, n}

9

задача

Напишите функцию / программу, которая принимает nв качестве параметра / ввода и печатает / возвращает количество топологий (как показано ниже) в наборе {1,2,...,n}.

Определение топологии

Пусть X - любое конечное множество, и предположим, что T, являющееся подмножеством множества степеней X (т. Е. Множества, содержащего подмножества X), удовлетворяет следующим условиям :

  1. X и пустой набор находятся в T.

  2. Если два множества U и V находятся в T, то объединение этих двух множеств находится в T.

  3. Если два множества U и V находятся в T, то пересечение этих двух множеств находится в T.

... тогда T называется топологией на X.

Характеристики

  1. Ваша программа либо:

    • функция, которая принимает nв качестве параметра
    • или программа, которая вводит n

    и печатает или возвращает количество (различных) топологий в наборе {1,2,...,n}.

  2. n это любое неотрицательное целое число, которое меньше 11 (конечно, нет проблем, если ваша программа обрабатывает n больше 11), и результат является положительным целым числом.

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

Пример ввода (значение n): 7

Пример вывода / возврата: 9535241

Вы можете проверить возвращаемое значение здесь или здесь .

Конечно, выигрывает самый короткий код.


Победитель определен, однако я могу сменить победителя, если появится более короткий код.

JiminP
источник
Должен ли он дать результаты в этом столетии или это достаточно хорошее доказательство правильности?
Питер Тейлор
@ Петр На самом деле, я понятия не имею, сколько времени это займет. Поэтому доказательство правильности программы достаточно хорошее, но программа все равно должна дать результат за разумное время, если n мало, например 4 ~ 5.
JiminP
@ JiminP, похоже, что вычисление его для n = 12 стоило того времени, и не существует известной формулы. В течение 4 или 5 я подозреваю, что это возможно через несколько минут грубой силой.
Питер Тейлор
Неправильное подмножество 2 ^ X также является топологией?
FUZxxl
@FUZxxl: Да. Я думаю, что это называется дискретной топологией .
JiminP

Ответы:

4

Хаскель, 144 персонажа

import List
import Monad
p=filterM$const[True,False]
f n=sum[1|t<-p$p[1..n],let e=(`elem`t).sort,e[],e[1..n],all e$[union,intersect]`ap`t`ap`t]

Практически прямая реализация спецификации, по модулю какая-то магия монад.

Очень медленно для n > 4.

Хаммар
источник
5

Питон, 147 символов

N=input()
S=lambda i,K:1+sum(0if len(set(j&k for k in K)-K)-1 else S(j+1,K|set(j|k for k in K))for j in range(i,2**N))
print S(1,set([0,2**N-1]))

Быстрый для N <= 6, медленный для N = 7, маловероятно, что N> = 8 когда-либо завершится.

Отдельные наборы представлены целочисленными битовыми масками, а топологии - наборами битовых масок. S(i,K)вычисляет количество различных топологий, которые вы можете сформировать, начиная с Kдобавления наборов с помощью битовых масок> = i.

Кит Рэндалл
источник
0

Zsh, 83 знака

Это решение соответствует букве ваших требований (но, конечно, не духу). Существует, несомненно, способ сжать цифры еще больше.

a=(0 3 S 9U 5CT 4HO6 5ODFS AMOZQ1 T27JJPQ 36K023FKI HW0NJPW01R);echo $[1+36#$a[$1]]
Жиль "ТАК - перестань быть злым"
источник
-1

Питон, 131 символ

lambda n:sum(x&(x>>2**n-1)&all((~(x>>i&x>>j)|x>>(i|j)&x>>(i&j))&1 for i in range(2**n)for j in range(2**n))for x in range(2**2**n))

Расширенная версия:

def f(n):
    count = 0
    for x in range(2**2**n): # for every set x of subsets of [n] = {1,...,n}
        try:
            assert x & 1 # {} is in x
            assert (x >> 2 ** n - 1) & 1 # [n] is in x
            for i in range(2**n): # for every subset i of [n]...
                if x >> i & 1: # ...in x
                    for j in range(2**n): # for every subset j of [n]...
                        if x >> j & 1: # ...in x
                            assert (x >> (i | j)) & 1 # their union is in x
                            assert (x >> (i & j)) & 1 # their intersection is in x
            count += 1
        except AssertionError:
            pass
    return count

Например, предположим, что n = 3. Возможные подмножества [n]:

0b000
0b001
0b010
0b011
0b100
0b101
0b110
0b111

где i-й бит указывает, находится ли я в подмножестве. Чтобы кодировать наборы подмножеств, мы замечаем, что каждое из этих подмножеств либо принадлежит, либо не принадлежит к рассматриваемому набору. Так, например,

x = 0b10100001
0b000 # 1
0b001 # 0
0b010 # 1
0b011 # 0
0b100 # 0
0b101 # 0
0b110 # 0
0b111 # 1

указывает, что x содержит {}, {2} и {1,2,3}.

user76284
источник
Не могли бы вы объяснить, как это работает?
Ad Hoc Garf Hunter
@AdHocGarfHunter Добавлена ​​расширенная версия.
user76284