Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Алгоритмы / 10.2 Алгоритм факторизации, основанный на полном переборе

.doc
Скачиваний:
27
Добавлен:
06.07.2016
Размер:
31.74 Кб
Скачать

Доклад на тему:

«Алгоритм факторизации, основанный на полном переборе»

Выполнил:

Литвинов Михаил

Б06-02

Алгоритм, основанный на полном переборе.

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

Пусть дано некоторое число N. Для его факторизации будет проводиться попытка его деления на все возможные числа от 2 до корня из N. Если делитель не будет найден, то, значит, число N – простое.

Распараллеливание этой задачи будет производиться следующим образом: изначально каждый процесс получает свой номер и общее количество потоков. Далее в каждом процессе происходит вычисление его нижней (корень из N, умноженный на номер процесса и делённый на их число) и верхней (то же самое, но к номеру процесса прибавляем единицу) границ, а затем — перебор всех чисел из заданного диапазона. В конце работы, после барьерной синхронизации, каждый процесс возвращает главному количество найденных делителей их массив.

Код:

#include <mpi.h>

#include <NTL/ZZ.h>

#include <iostream>

#include <math.h>

#include <vector>

using namespace std;

// Макрос для подключения NTL

NTL_CLIENT

int main(int argc, char *argv[])

{

int size, rank;

MPI_Init(&argc, &argv);

// Узнаём число процессов

MPI_Cоmm_size(MPI_COMM_WORLD, &size);

// И номер текущего процесса

MPI_Cоmm_rank(MPLCOMIVLWORLD, &rank);

// и число для факторизации

long N;

if (rank ==0)

{

// Ввод — только для корневого процессора

cin >> N;

}

// Рассылаем число остальным процессорам

MPI_Bcast(&N, 1, MPI_LONG, O, MPI_COMM_WORLD);

long low_bound, high_bound;

// Вычисляем верхнюю и нижнюю границы

low_bound = (long)(floor(sqrt((double)N))*(double)rank/(double)size);

high_bound = (long)(floor(sqrt((double)N))*(double)(rank+1)/(double)size);

if (rank == (size-1))

{

high_bound++;

}

PrimeSeq seq;

// Инициализируем генератор простых чисел

seq.reset (10w_b0und);

vector<long>result;

long X;

do

{

X = seq.next();

// Пока не переберём всё множество

if (X!=0 && X< high_bоund)

{

if(N %X==0)

{ // Проверяем, является ли Х делителем

result.push_back(X); // Если да, добавляем его

}

}

}

while (X!=0 && X< high_bound);

// Ожидаем завершения вычислений всеми процессорами

1\IPI_Barrier(MPI_COMM.WORLD);

// Сводим результат воедино

long res_count = result.size();

long temp_value;

MPI_Status status;

if (rank == 0 )

{

// Корневой процесс принимает данные от всех остальных

for (int i = 1; i < size; i++)

{

MPI_Recv(&res_count, 1, MPLLONG, i, 0, MPI_COMM_WORLD,

&status);

for (int j = 0; j < res_count; j++)

{

MPI_Recv(&temp_va1ue, 1, MPLLONG, i, 0, MPI_COMM_WORLD,

&status);

// И добавляет их в свой вектор делителей

result.push_back(temp_va1ue);

else

{

// Передача данных

// Отправляем число найденных делителей

MPI_Send(&res_count, 1, MPLLONG, O, 0, MPI_COMM_WORLD);

for (int j = 0; j < res_count; j++)

{

// Отправляем делители по-одному

temp_va1ue = resu1t[j];

MPI_Send(&temp.Value, 1, MPLLONG, 0, 0, MPLCOMMNVORLD);

}

}

// Выводим найденные делители

if (rank == 0)

{

for (vector<long> ::iterator t = resu1t.begin(); t <resu1t.end(); ++t)

{

cout << *t << " ";

}

cout << endl;

}

// Завершаем работу программы

MPLFinalize();

return 0;

Пример:

Факторизуем число 1073 с использованием 3 процессов:

Целая часть корня: 32

Диапазоны: [2-11][12-21][22-32] (с округлением вверх, 0, 1 не считается)

№0

число

2

3

4

5

6

7

8

9

10

11

вернёт

остаток

1

2

1

3

5

2

1

2

3

6

№1

число

12

13

14

15

16

17

18

19

20

21

вернёт

остаток

5

7

9

8

1

2

11

9

13

2

№2

число

22

23

24

25

26

27

28

29

30

31

32

вернёт

остаток

17

15

17

23

7

20

9

0

23

19

17

1; [29]

Результат — 1073 сложное число, кратное 29 и, следовательно, 37

Временная сложность.

Как несложно заметить, для факторизации числа N необходимо N^(1/2) операций деления, или N^(1/2)/p на каждом из p процессоров.