Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Лаб. 4 АиСД (Вариант 15).docx
Скачиваний:
6
Добавлен:
01.09.2024
Размер:
176.29 Кб
Скачать

Ответы на вопросы:

Лаб. Раб. №5:

  1. Какова структура машины Тьюринга?

На рис.1 представлена структурная схема машины Тьюринга, где

обозначены буквами:

B – внешняя память машины, которую можно интерпретировать,

как неограниченную в обе стороны ленту, разделенную на элементарные ячейки;

Q – внутренняя память машины, определяющая состояния, в которых находится машина в любой момент времени;

G – считывающая (записывающая) головка;

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

одного состояния в другое;

P – устройство, управляющее головкой.

  1. Что такое внутренняя и внешняя память машины Тьюринга?

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

Q – внутренняя память машины, определяющая состояния, в которых находится машина в любой момент времени;

  1. В чем заключается особенность построения функциональных таблиц?

Исходными данными являются двоичные символы 0 и 1. Работа

алгоритма определяется четырьмя состояниями: q0, q1, q2, qk.

Тройка символов q10R, записанная на пересечении строки q0 и

столбца 0, означает: если машина находится в состоянии q0 и с ленты

будет считан символ 0, то машина перейдет в состояние q1, на ленту будет записан символ 0, и головка сдвинется на один символ вправо.

  1. Какова связь функциональной таблицы с функциональной диаграммой?

  1. В чем смысл умножения машин Тьюринга?

Система команд (таблица или диаграмма) машины Т является результатом объединения системы команд машин T1 и T2. Нетрудно видеть, что машина Т = T1·T2 работает так, как если бы после завершения работы машины T1 начала работать машина T2. Очевидно, что произведение машины Тьюринга некоммутативно, т.е. T1· T2 ≠ T2 T1.

  1. Что такое итерация машин Тьюринга?

Итерация машин Тьюринга заключается в отождествлении r-го состояния останова машин Тьюринга с начальным состоянием.

Код на C++ лр2:

#include <iostream>

#include <vector>

#include <queue>

#include <utility>

#include <cstring>

#include <climits>

using namespace std;

// `N` - общее количество узлов на Graphе или городов на карте

#define N 5

// Сторожевое значение для представления `INFINITY`

#define INF INT_MAX

// Узлы State Space Tree

struct Node

{

// сохраняет ребра дерева в пространстве состояний

// помощь в отслеживании пути при нахождении ответа

vector<pair<int, int>> path;

// сохраняет уменьшенную матрицу

int reducedMatrix[N][N];

// сохраняет нижнюю границу

int cost;

// сохраняет текущий номер города

int vertex;

// сохраняет общее количество посещенных городов

int level;

};

// Функция выделения нового узла `(i, j)` соответствует посещению города `j`

// из города `i`

Node* newNode(int parentMatrix[N][N], vector<pair<int, int>> const &path,

int level, int i, int j)

{

Node* node = new Node;

// сохраняет ребра-предки дерева в пространстве состояний

node->path = path;

// пропустить корневой узел

if (level != 0)

{

// добавляем к пути текущее ребро

node->path.push_back(make_pair(i, j));

}

// копируем данные из родительского узла в текущий узел

memcpy(node->reducedMatrix, parentMatrix,

sizeof node->reducedMatrix);

// Изменяем все записи строки `i` и столбца `j` на `INFINITY`

// пропустить корневой узел

for (int k = 0; level != 0 && k < N; k++)

{

// устанавливаем исходящие ребра для города `i` в `INFINITY`

node->reducedMatrix[i][k] = INF;

// устанавливаем входящие ребра в город `j` на `INFINITY`

node->reducedMatrix[k][j] = INF;

}

// Установите `(j, 0)` в `INFINITY`

// здесь начальный узел равен 0

node->reducedMatrix[j][0] = INF;

// установить количество посещенных городов на данный момент

node->level = level;

// присваиваем номер текущего города

node->vertex = j;

// return node

return node;

}

// Функция для сокращения каждой строки так, чтобы в каждой строке был хотя бы один ноль

int rowReduction(int reducedMatrix[N][N], int row[N])

{

// инициализируем массив строк значением `INFINITY`

fill_n(row, N, INF);

// `row[i]` содержит минимум в строке `i`

for (int i = 0; i < N; i++)

{

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

{

if (reducedMatrix[i][j] < row[i]) {

row[i] = reducedMatrix[i][j];

}

}

}

// уменьшаем минимальное значение каждого элемента в каждой строке

for (int i = 0; i < N; i++)

{

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

{

if (reducedMatrix[i][j] != INF && row[i] != INF) {

reducedMatrix[i][j] -= row[i];

}

}

}

}

// Функция для уменьшения каждого столбца так, чтобы там был хотя бы один ноль

// в каждом столбце

int columnReduction(int reducedMatrix[N][N], int col[N])

{

// инициализируем все элементы массива `col` значением `INFINITY`

fill_n(col, N, INF);

// `col[j]` содержит минимум в col `j`

for (int i = 0; i < N; i++)

{

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

{

if (reducedMatrix[i][j] < col[j]) {

col[j] = reducedMatrix[i][j];

}

}

}

// уменьшаем минимальное значение каждого элемента в каждом столбце

for (int i = 0; i < N; i++)

{

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

{

if (reducedMatrix[i][j] != INF && col[j] != INF) {

reducedMatrix[i][j] -= col[j];

}

}

}

}

// Функция для получения нижней границы пути, начинающегося с текущего минимального узла

int calculateCost(int reducedMatrix[N][N])

{

// инициализировать стоимость до 0

int cost = 0;

// Сокращение строк

int row[N];

rowReduction(reducedMatrix, row);

// Сокращение столбца

int col[N];

columnReduction(reducedMatrix, col);

// общая ожидаемая стоимость равна сумме всех сокращений

for (int i = 0; i < N; i++)

{

cost += (row[i] != INT_MAX) ? row[i] : 0,

cost += (col[i] != INT_MAX) ? col[i] : 0;

}

return cost;

}

// Функция для печати списка посещенных городов по наименьшей стоимости

void printPath(vector<pair<int, int>> const &list)

{

for (int i = 0; i < list.size(); i++) {

cout << list[i].first + 1 << " —> " << list[i].second + 1 << endl;

}

}

// Объект сравнения, который будет использоваться для упорядочивания кучи

struct comp

{

bool operator()(const Node* lhs, const Node* rhs) const {

return lhs->cost > rhs->cost;

}

};

// Функция для решения задачи о коммивояжёре с использованием метода ветвей и границ

int solve(int costMatrix[N][N])

{

// Создаем приоритетную очередь для хранения активных узлов дерева поиска

priority_queue<Node*, vector<Node*>, comp> pq;

vector<pair<int, int>> v;

// создаем корневой узел и вычисляем его стоимость.

// TSP начинается с первого города, т.е. узла 0

Node* root = newNode(costMatrix, v, 0, -1, 0);

// получаем нижнюю границу пути, начинающегося в узле 0

root->cost = calculateCost(root->reducedMatrix);

// Добавляем корень в список живых узлов

pq.push(root);

// Находит живой узел с наименьшей стоимостью, добавляет его потомков в список

// живые узлы и, наконец, удаляем их из списка

while (!pq.empty())

{

// Находим активный узел с наименьшей оценочной стоимостью

Node* min = pq.top();

// Найденный узел удаляется из списка живых узлов

pq.pop();

// `i` хранит текущий номер города

int i = min->vertex;

// если все города посещены

if (min->level == N - 1)

{

// вернуться в начальный город

min->path.push_back(make_pair(i, 0));

// вывести список посещенных городов

printPath(min->path);

// возвращаем оптимальную стоимость

return min->cost;

}

// делаем для каждого дочернего элемента min

// `(i, j)` образует ребро в пространственном дереве

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

{

if (min->reducedMatrix[i][j] != INF)

{

// создаем дочерний узел и вычисляем его стоимость

Node* child = newNode(min->reducedMatrix, min->path,

min->level + 1, i, j);

/* Стоимость дочернего элемента =

стоимость родительской ноды +

стоимость ребра(i, j) +

нижняя граница пути, начинающегося в узле j

*/

child->cost = min->cost + min->reducedMatrix[i][j]

+ calculateCost(child->reducedMatrix);

// Добавляем дочерний элемент в список активных узлов

pq.push(child);

}

}

// свободный узел, так как мы уже сохранили ребра `(i, j)` в векторе.

// Так что нет необходимости в родительском узле при печати решения.

delete min;

}

}

int main()

{

// матрица затрат для задачи коммивояжера.

/*

int costMatrix[N][N] =

{

{INF, 5, INF, 6, 5, 4},

{5, INF, 2, 4, 3, INF},

{INF, 2, INF, 1, INF, INF},

{6, 4, 1, INF, 7, INF},

{5, 3, INF, 7, INF, 3},

{4, INF, INF, INF, 3, INF}

};

*/

// стоимость 34

int costMatrix[N][N] =

{

{ INF, 7, 12, 25, 10 },

{ 10, INF, 9, 5, 11 },

{ 13, 8, INF, 6, 4 },

{ 6, 11, 15, INF, 15 },

{ 5, 9, 12, 17, INF }

};

/* С удалением ребра

int costMatrix[N][N] =

{

{ INF, 7, 12, 25, 10 },

{ 10, INF, 9, INF, 11 },

{ 13, 8, INF, 6, 4 },

{ 6, 11, 15, INF, 15 },

{ 5, 9, 12, 17, INF }

};

*/

/*

// стоимость 16

int costMatrix[N][N] =

{

{INF, 3, 1, 5, 8},

{3, INF, 6, 7, 9},

{1, 6, INF, 4, 2},

{5, 7, 4, INF, 3},

{8, 9, 2, 3, INF}

};

*/

/*

// стоимость 8

int costMatrix[N][N] =

{

{INF, 2, 1, INF},

{2, INF, 4, 3},

{1, 4, INF, 2},

{INF, 3, 2, INF}

};

*/

/*

// стоимость 12

int costMatrix[N][N] =

{

{INF, 5, 4, 3},

{3, INF, 8, 2},

{5, 3, INF, 9},

{6, 4, 3, INF}

};

*/

cout << "\n\nTotal cost is\n" << solve(costMatrix);

return 0;

}

Код на C++ лр5:

#include <iostream>

#include <string>

#include <stdexcept>

using namespace std;

string convert(string unary_input) {

int result = 0;

if (unary_input.empty()) {

unary_input = "0";

} else {

for (size_t i = 0; i < unary_input.length(); ++i) {

if (unary_input[i] != '|') {

throw invalid_argument("Введена не унарная запись");

}

result += 1;

if (result > 9) {

return string(1, unary_input[result - 2]);

}

unary_input[i] = '0' + result;

}

}

return string(1, unary_input[result - 1]);

}

int main() {

string unary_input = "||||";

string result = convert(unary_input);

cout << unary_input << ": " << result << endl;

return 0;

}