Gere algoritmicamente todos os pontos da grade dentro de um hipercubo

8

O problema vem diretamente da matemática computacional e pode ser indicado da seguinte forma:

Dada uma matriz regular , encontre efetivamente todos os vetores modo que \ n {Mv} \ leq1 , em que \ n {Mv} seja o componente máximo do vetor em módulo.MRd×dvZd__Mv__1__Mv__

Dou um algoritmo abaixo, mas é muito ineficiente, pois possui muito mais etapas do que o número de pontos da grade. Ainda é suportável para d=5 no meu caso, mas falha completamente para d=6 , não tenho muito tempo; além disso, eu gostaria de fazer algum trabalho em dimensões mais altas também.


Meu algoritmo atual é baseado no seguinte (aviso: contém mais contas matemáticas): Primeiro, calcule __M-1__ . Então, observamos que __v____M-1____Mv____M-1__ . Isso significa que podemos calcular eu=chão__M-1__ e tentar todos os vetores v{-eu,-eu+1,,eu-1,eu}d ; há exatamente (2eu+1)d deles. (E aqui está o problema: se d=6 e eu=18 , eu recebo 2.5E9 iterações, que são ordens de magnitude maiores que o número de pontos que acho que existem.)

yo '
fonte
1
Você já pensou em formular seu problema como um programa linear inteiro e depois contar soluções? Eu acho que existem métodos disponíveis nos resolvedores de IP (por exemplo, CPLEX) para fazer isso, mas não sei o quão rápido eles são na prática. Um método para fazer isso é conhecido como algoritmo de Barvinok.
Cornelius Brand
@ C.Brand Obrigado, vou dar uma olhada nele (no entanto, faz muito tempo que não vejo nenhum LP / IP pela última vez). Por acaso, você tem uma idéia de se isso está presente no SageMath?
yo '
Quanto às suas preocupações, a formulação original do problema já é (quase) um programa inteiro; a única coisa que você precisará cuidar é o uso da (não linear) -norm. Mas não tenho idéia se um algoritmo para contar soluções IP está disponível no SageMath.
Cornelius Brand

Respostas:

3

Aqui está uma outra maneira de olhar para o problema: Você tem uma rede gerado pelas colunas de . Use o algoritmo Lenstra-Lenstra-Lovász (LLL) para obter uma base reduzida dessa estrutura. Se você substituir por uma nova matriz formada pela saída de LLL, as colunas de ainda gerarão a mesma rede, mas os vetores de base estarão mais próximos de serem ortogonais entre si e as entradas de deve ter magnitude menor.MMMM-1

De lá, também ajudaria a obrigados cada componente do separadamente: ou seja, você pode obrigado a th componentepor. (A propósito, o limite não está correto; precisamos usar a soma dos elementos em cada linha, não o máximo.)vEu|vEu|j=1d|(M-1)Euj|__v____M-1__

Para valores de até cerca de 30, o algoritmo LLL terminará praticamente instantaneamente. Assintoticamente, é preciso , então ele diminui a velocidade para muito grande , mas, ao mesmo tempo, o número de pontos que precisamos verificar cresce exponencialmente em , portanto o tempo de execução da LLL não é realmente o gargalo. Por outro lado, a economia no número de pontos que precisam ser verificados pode ser enorme. Escrevi um código GAP para gerar uma matriz regular aleatória (estocástica) e comparar os limites nos componentes dedO(d6)ddMv que obtemos usando a base original, em comparação com a base reduzida de LLL (a propósito, não precisamos assumir que a matriz é regular; eu fiz essa restrição apenas porque esse era o caso em sua aplicação):

d: = 8;
M: = IdentityMat (d);
para i em [1..d] faça
  para j em [1..d] faça
    M [i] [j]: = Aleatório ([- 10 ^ 8..10 ^ 8]);
  od;
  M [i]: = M [i] / Soma (M [i]);
od;
L: = LLLReducedBasis (M) .base;
MM: = M ^ -1 * 1,0;
LL = L ^ -1 * 1,0;
para i em [1..d] faça
  para j em [1..d] faça
    MM [i] [j]: = MM [i] [j] * SignFloat (MM [i] [j]);
    LL [i] [j]: = LL [i] [j] * SignFloat (LL [i] [j]);
  od;
od;

Imprimir ("Limites para a base original:");
ones: = [1..d] * 0 + 1;
v: = MM * uns;
para i em [1..d] faça
  v [i]: = Int (Piso (v [i]));
  Imprimir (v [i]);
  Impressão(" ");
od;
Imprimir ("\ n ("));
Imprimir (Produto (v * 2 + 1));
Imprimir ("aponta para verificar) \ n");

Print ("Limites para LLL:");
v: = LL * uns;
para i em [1..d] faça
  v [i]: = Int (Piso (v [i]));
  Imprimir (v [i]);
  Impressão(" ");
od;
Imprimir ("\ n ("));
Imprimir (Produto (v * 2 + 1));
Imprimir ("aponta para verificar) \ n");

A saída a seguir (com base na semente aleatória padrão, com ) não é atípica:d=8

Limites para a base original: 9 23 24 4 23 16 23 4 
(258370076349 pontos para verificar)
Limites para a base de LLL: 3 3 2 2 3 4 2 3 
(2701125 pontos para verificar)

Edit : Este problema é um caso especial do problema geral de enumerar pontos de treliça em politopos convexos, o que resulta ser um problema bem estudado, e existem algoritmos mais eficientes do que o descrito acima. Veja este artigo para uma pesquisa.

Brent Kerby
fonte
Pensei em obter uma boa base da grade primeiro, mas não tenho certeza de quão eficiente ela é em altas dimensões? (Nota: O problema não está interessante para mim desde que conseguimos contorná-la completamente, mas eu vou tentar manter um olho sobre esta questão ainda.)
yo'
Adicionei um pouco mais à minha resposta, com algumas informações sobre a eficiência da LLL, bem como código e saída de exemplo.
Brent Kerby