2014 dxdy logo

Научный форум dxdy

Математика, Физика, Computer Science, Machine Learning, LaTeX, Механика и Техника, Химия,
Биология и Медицина, Экономика и Финансовая Математика, Гуманитарные науки


Правила форума


Посмотреть правила форума



Начать новую тему Ответить на тему
 
 Не работает обратное преобразование Фурье над конечным полем
Сообщение20.12.2023, 17:18 
Аватара пользователя


03/01/23
73
Здравствуйте. Помогите, пожалуйста, разобраться в реализации дискретного преобразования Фурье над конечным полем, нужного для умножения многочленов.

Формулы. Прямое преобразование

$D_k = \sum\limits_{i=0}^{n-1}{\omega}^{ik}{d}_{i}$

Обратное преобразование:

$S_k = \frac{1}{n}\sum\limits_{i=0}^{n-1}{\omega}^{-ik}{D}_{i}$

Я взял многочлен $1+2x+3x^2+4x^3+5x^4$ со списком коэффициентов $(1, 2, 3, 4, 5)$ над полем ${Z}_{13}$ и нахожу от него преобразование Фурье:

Изображение

Здесь двойка - корень из единицы степени 12 в поле ${Z}_{13}$, от 0 до 4 идет проход по коэффициентам многочлена. Преобразование Фурье равно $(2, 12,7,0,1)$

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

Изображение

Здесь число 7 - обратный элемент поля для элемента 2, нужен, чтобы избавиться от минуса в показателе степени. Число ${5}^{-1}$ - обратный для $n=5$. Видим, что получился совсем не исходный вектор. Почему так? Почему не сработало обратное преобразование Фурье?

 Профиль  
                  
 
 Re: Не работает обратное преобразование Фурье над конечным полем
Сообщение24.12.2023, 01:14 
Заслуженный участник
Аватара пользователя


23/07/08
10910
Crna Gora
Давайте сначала исправим программу, а потом будем её оптимизировать.
На данном этапе любой многочлен должен задаваться вектором из 12 коэффициентов:
$[a_0,a_1,a_2,a_3,a_4,a_5,a_6,a_7,a_8,a_9,a_{10},a_{11}]$
Работаем только с такими векторами. Поэтому замените вектор $[1,2,3,4,5]$ на $[1,2,3,4,5,0,0,0,0,0,0,0]$.

Теперь в формулах везде возьмите $n=12$. Во всех циклах (как for, так и $\Sigma$) переменная цикла должна пробегать значения от $0$ до $n-1=11$ включительно.

Найдите теперь $D_k$, а потом $S_k$. Что получилось?

 Профиль  
                  
 
 Re: Не работает обратное преобразование Фурье над конечным полем
Сообщение24.12.2023, 10:07 
Аватара пользователя


03/01/23
73
Спасибо за ответ. Так уже лучше - в результате обратного преобразования Фурье появились нули там, где они были, но информационные значения по-прежнему неправильные.

${D}_{k} = [2, 12, 7, 0, 1, 3, 3, 5, 12, 6, 7, 6]$

$S_k =  [5, 10, 2, 7, 12, 0, 0, 0, 0, 0, 0, 0]$

 Профиль  
                  
 
 Re: Не работает обратное преобразование Фурье над конечным полем
Сообщение24.12.2023, 17:48 
Заслуженный участник
Аватара пользователя


23/07/08
10910
Crna Gora
Without Name
$D_k$ — совершенно правильно.
$S_k$ — получились такие потому, что Вам надо поставить $n=12$ везде, в том числе здесь:
$S_k = \dfrac{1}{\color{magenta}n}\sum\limits_{i=0}^{n-1}{\omega}^{-ik}{D}_{i}$
А Вы делили по-прежнему на $5$.

 Профиль  
                  
 
 Re: Не работает обратное преобразование Фурье над конечным полем
Сообщение24.12.2023, 17:55 
Аватара пользователя


03/01/23
73
Ого! Спасибо, все получилось! Пойду реализовывать этот алгоритм на C++

 Профиль  
                  
 
 Re: Не работает обратное преобразование Фурье над конечным полем
Сообщение24.12.2023, 18:22 
Заслуженный участник
Аватара пользователя


23/07/08
10910
Crna Gora
Without Name
Это здорово! :-) Позвольте ещё несколько замечаний.

0) Обратите внимание, что если в векторе $D_k$ после вычисления обнулить (или как-то ещё испортить) даже только $D_{11}$, уже ничего не получится. В этом, собственно, и была ошибка: исходный многочлен четвёртой степени, а его преобразование Фурье — максимальной.

1) У исходного многочлена только пять первых коэффициентов отличны от нуля. Поэтому, в принципе, первый цикл for первое суммирование можно сделать от 0 до 4. Но поскольку в будущем это, вероятно, будет библиотечная функция, я бы не советовал этого делать.

2) Всё это желательно проверить на нескольких многочленах случайной ($0...11$) степени и со случайными ($0...12$) коэффициентами.

3) Деление на $12$ есть умножение на $-1$, поскольку $12x+x=13x=0$.

4) В реализации на C++ я бы все операции реализовал в виде таблиц (lookup tables). Особенно напрашивается заранее вычислить массив $2^n$.

 Профиль  
                  
 
 Re: Не работает обратное преобразование Фурье над конечным полем
Сообщение24.12.2023, 18:28 
Аватара пользователя


03/01/23
73
Спасибо! Отличные замечания

 Профиль  
                  
 
 Re: Не работает обратное преобразование Фурье над конечным полем
Сообщение24.12.2023, 23:34 
Аватара пользователя


03/01/23
73
Что у меня не так в реализации? Почему-то вектор после преобразования получается не такой, какой получился в Maple

Код:
inline constexpr int FT_LENGTH = 12;

// Таблица для 2^n mod 13
int exp_table[13] = {
   1,
   2,
   4,
   8,
   3,
   6,
   12,
   11,
   9,
   5,
   10,
   7,
   1
};

int mul_table[13][13] = {
   { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
   { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 },
   { 0, 2, 4, 6, 8, 10, 12, 1, 3, 5, 7, 9, 11 },
   { 0, 3, 6, 9, 12, 2, 5, 8, 11, 1, 4, 7, 10 },
   { 0, 4, 8, 12, 3, 7, 11, 2, 6, 10, 1, 5, 9 },
   { 0, 5, 10, 2, 7, 12, 4, 9, 1, 6, 11, 3, 8 },
   { 0, 6, 12, 5, 11, 4, 10, 3, 9, 2, 8, 1, 7 },
   { 0, 7, 1, 8, 2, 9, 3, 10, 4, 11, 5, 12, 6 },
   { 0, 8, 3, 11, 6, 1, 9, 4, 12, 7, 2, 10, 5 },
   { 0, 9, 5, 1, 10, 6, 2, 11, 7, 3, 12, 8, 4 },
   { 0, 10, 7, 4, 1, 11, 8, 5, 2, 12, 9, 6, 3 },
   { 0, 11, 9, 7, 5, 3, 1, 12, 10, 8, 6, 4, 2 },
   { 0, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1 }
};

void forward_transform(const int(&source)[FT_LENGTH], int(&target)[FT_LENGTH])
{
   for (int k = 0; k < FT_LENGTH; ++k)
   {
      int sum = 0;
      for (int i = 0; i < FT_LENGTH; ++i)
      {
         sum += exp_table[(i * k) % 13] * source[i];
      }
      target[k] = sum % 13;
   }
}

int main()
{
    int a[12] = {1, 2, 3, 4, 5, 0, 0, 0, 0, 0, 0, 0};
    int b[12] = { 0 };
    int c[12] = { 0 };

    forward_transform(a, b);
    inverse_transform(b, c);

    return 0;
}

 Профиль  
                  
 
 Re: Не работает обратное преобразование Фурье над конечным полем
Сообщение25.12.2023, 00:11 
Заслуженный участник
Аватара пользователя


23/07/08
10910
Crna Gora
Начнём с какого-то элемента $a$ и будем прибавлять единицу. Чтобы вернуться к $a$, нам надо $13$ раз прибавить единицу.
Начнём с какого-то элемента $a\neq 0$ и будем умножать на $2$. Чтобы вернуться к $a$, нам надо $12$ раз умножить на $2$.
Почему такая разница? В процессе прибавления единицы мы переберём все 13 элементов поля. А в процессе умножения на $2$ мы не можем получить нуль (если только не начали с нуля). А если бы мы чудом нуль получили, все дальнейшие результаты умножения тоже были бы нулями.

Поэтому
sum += exp_table[(i * k) % 13] * source[i]; // ошибка! заменить 13 на 12
но
target[k] = sum % 13; // правильно

Поэтому последнее значение в exp_table является излишним (да Вы и сами видите, что это уже повтор), этот массив должен содержать лишь 12 элементов.

 Профиль  
                  
 
 Re: Не работает обратное преобразование Фурье над конечным полем
Сообщение25.12.2023, 00:30 
Аватара пользователя


03/01/23
73
Ааа, понятно, спасибо

 Профиль  
                  
 
 Re: Не работает обратное преобразование Фурье над конечным полем
Сообщение25.12.2023, 00:33 
Заслуженный участник
Аватара пользователя


23/07/08
10910
Crna Gora
Without Name
Вам респект за то, что не ставите открывающие скобки так:
Используется синтаксис C++
   for (int k = 0; k < FT_LENGTH; ++k) {
      int sum = 0;
      for (int i = 0; i < FT_LENGTH; ++i) {
         sum += exp_table[(i * k) % 13] * source[i];
      }
      target[k] = sum % 13;
   }
А следуете моему любимому стилю Оллмана (который у меня установился как-то сам собой).

 Профиль  
                  
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ Сообщений: 11 ] 

Модераторы: Модераторы Математики, Супермодераторы



Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group