русс | укр

Языки программирования

ПаскальСиАссемблерJavaMatlabPhpHtmlJavaScriptCSSC#DelphiТурбо Пролог

Компьютерные сетиСистемное программное обеспечениеИнформационные технологииПрограммирование

Все о программировании


Linux Unix Алгоритмические языки Аналоговые и гибридные вычислительные устройства Архитектура микроконтроллеров Введение в разработку распределенных информационных систем Введение в численные методы Дискретная математика Информационное обслуживание пользователей Информация и моделирование в управлении производством Компьютерная графика Математическое и компьютерное моделирование Моделирование Нейрокомпьютеры Проектирование программ диагностики компьютерных систем и сетей Проектирование системных программ Системы счисления Теория статистики Теория оптимизации Уроки AutoCAD 3D Уроки базы данных Access Уроки Orcad Цифровые автоматы Шпаргалки по компьютеру Шпаргалки по программированию Экспертные системы Элементы теории информации

Выполнение работы


Дата добавления: 2015-08-31; просмотров: 705; Нарушение авторских прав


В этой лабораторной работе мы подробно рассмотрим технику, известную как поиск в пространстве состояний. Каждая конфигурация, в которой может пребывать система, называется состоянием. Из каждого состояния можно переместиться в некоторое множество других состояний. Одно состояние называется стартовым, другое – целевым. Задача состоит в том, чтобы найти последовательность перемещений, ведущих из стартового состояния в целевое. В лабораторной работе применение алгоритмов поиска в пространстве состояний мы рассмотрим на примере задачи поиска пути в лабиринте. Пусть, есть такой лабиринт:

#####

#O#X#

# #

#####

Позиция, помеченная как 'O' – стартовая позиция; позиция, помеченная 'X' – целевая. Знаком '#' изображаются непрозрачные стены. Мы можем на каждом шаге перемещаться ВВЕРХ, ВЛЕВО, ВПРАВО или ВНИЗ. Одно из правильных решений этого лабиринта можно задать следующей серией перемещений: ВНИЗ ВПРАВО ВПРАВО ВВЕРХ

Конечно, другим правильным решением может быть следующая серия перемещений:

ВНИЗ ВВЕРХ ВНИЗ ВВЕРХ ВНИЗ ВПРАВО ВЛЕВО ВПРАВО ВПРАВО ВВЕРХ ВНИЗ ВВЕРХ

Итак, каждое состояние описывается:

- расположением стен;

- стартовой позицией;

- целевой позицией.

После того как сделано перемещение, новое состояние подобно старому, но содержит другую стартовую позицию.

Прежде чем писать «решатель лабиринтов», мы напишем универсальный инструмент поиска (который ничего не знает о лабиринтах), и применим его к задаче поиска пути в лабиринте. Один из алгоритмов поиска пространства состояний называется поиском преимущественно в глубину (depth-firth search). По этому алгоритму, когда из исходного состояния (s) получено новое (n), это новое состояние включается в поиск. Теперь мы пытаемся перевести систему из состояния n в состояние n1. Если состояние n1 ранее не было достигнуто, то производится его просмотр и поиск продолжается из n1. В противном случае выбирается другое достижимое из n состояние, и т. д. Например, предположим, что мы осуществляем поиск в следующем лабиринте:



######

## #

#O #X#

## #

######

Предположим, что когда мы ищем следующее состояние, мы пытаемся выполнять перемещения в следующем порядке: ВВЕРХ, ВПРАВО, ВНИЗ, ВЛЕВО. Поиск в глубину попытается перевести систему в новое состояние используя вначале перемещение ВВЕРХ. Это перемещение блокируется стеной. Следующим выбирается перемещение ВПРАВО. Получим такое состояние лабиринта:

######

## #

# O#X#

## #

######

Пытаемся переместиться ВВЕРХ. Получим следующее состояние:

######

##O #

# #X#

## #

######

После нескольких применений перемещения ВПРАВО перемещение ВНИЗ приводит к достижению цели.

В противоположность этому поиску, поиск преимущественно в ширину (breadth-first search) сначала осуществляет поиск по всем узлам уровня k, а затем уже – по узлам уровня k+1. Поиск преимущественно в ширину для этого же лабиринта сначала применит перемещение ВПРАВО. Получим:

######

## #

# O#X#

## #

######

Затем применим перемещение ВВЕРХ. Получим:

######

##O #

# #X#

## #

######

Поскольку это не конечное состояние, возвращаемся назад и пытаемся применить перемещение ВНИЗ. Получим:

######

## #

# #X#

##O #

######

Поскольку это не конечное состояние, возвращаемся назад и пытаемся применить перемещение ВПРАВО. Получим:

######

## O #

# #X#

## #

######

И т. д. Другими словами поиск в ширину просматривает все состояния, которые находятся на расстоянии k перемещений от начального, прежде, чем просматривает какое-либо состояние, которое находится на расстоянии k+1.

Функции поиска

Для перехода в следующее состояние используется функция поиска. Алгоритм поиска в дереве состояний следующий:

1. Если нет доступных состояний, мы не можем найти решение.

2. В противном случае, если исходное состояние целевое, то вернуть это состояние.

3. В противном случае переходим из исходного состояния в новое. Затем формируем новое множество состояний (включаем новое состояние в список состояний).

4. Новое состояние становится исходным.

5. Перейти к пункту 1.

 

Функция поиска по дереву – tree-searchполучает четыре параметра:

states – список состояний;

is-goal – предикат is-goal получает в качестве аргумента состояние. Если состояние целевое, is-goal возвращает не NIL. В противном случае, возвращает NIL.

expand-state – получает в качестве аргумента какое-то состояние. Возвращает список всех состояний, которые могут быть достигнуты из заданного состояния, за одно перемещение. (Список может быть пустым, если нет состояний, достижимых из заданного).

combine-states – функция combine-states получает два аргумента. Первый аргумент – список уже существующих состояний. Второй аргумент – список сгенерированных функцией expand-state состояний. Функция возвращает список состояний просто объединяя все состояния в обоих списках. Порядок, в котором состояния представлены в списке, это порядок, в котором состояния были получены.

Используя различные версии функций is-goal, expand-state, combine-states мы можем реализовать почти каждый поисковый алгоритм, использующий поиск по дереву.

Рекурсивная версия функции поиска по дереву.

(defun tree-search

(states is-goal expand-state combine-states)

(cond ((null states) nil)

((funcall is-goal (first states))

(first states))

(t (tree-search

(funcall combine-states (rest states)

(funcall expand-state (first states)))

is-goal

expand-state

combine-states ))))

Эта функция выполняет поиск по дереву, начиная с состояний заданных аргументом states, пока не будет достигнуто состояние, для которого предикат is-goal вернет значение не NIL. Функция expand-state используется для генерации новых состояний, достижимых из данного. Функция combine-states используется для объединения сгенерированных состояний с предыдущими. Поиск реализован рекурсивно.

Теперь мы можем использовать функцию поиска по дереву –tree-searchдля реализации алгоритмов поиска в глубину и в ширину.

Функция поиска в глубину – depth-first-searchимеет следующий вид:

(defun depth-first-search

(state is-goal expand-state tree-searcher)

(funcall tree-searcher

(list state) is-goal expand-state

#'(lambda (old-states new-states)

(append new-states old-states)))

)

Функция depth-first-searchвыполняет поиск в глубину, начиная с состояния state, до тех пор, пока не будет найдено целевое состояние. Функция expand-state используется для генерации дочерних состояний. Функция tree-searcher используется для выполнение алгоритма поиска по дереву.

Лабиринт

Лабиринт представим структурой. Структура для описания лабиринта должна иметь следующие поля: строку и столбец начальной позиции, и строку и столбец целевой позиции. В структуру входит также двумерный массив, который показывает расположение стен в лабиринте.

(defstruct maze «Двумерный лабиринт»

start-row ; Строка начальной позиции.

start-column ; Столбец начальной позиции.

goal-row ; Строка целевой позиции.

goal-column ; Столбец целевой позиции.

grid ; Двумерный массив элементы которого принимают

; значение не NIL, там где в лабиринте расположены

; стены, и NIL - на свободных местах. Первый индекс

; массива - индекс строк, второй - индекс столбцов.

; Нумерация начинается с нуля.

;Например, индекс элемента, расположенного во

; второй строке и третьем столбце - (1, 2).

)

Мы можем представить состояние как список из двух элементов. Первый элемент списка – список уже посещенных позиций на пути из стартовой позиции к текущей. Второй элемент списка – лабиринт, который представлен, как описано выше.

Функция печати лабиринта maze-printполучает два аргумента: лабиринт и список пройденных позиций:

(defun maze-print (maze positions)

...

)

Для печати переданного лабиринта функция использует несколько символов:

- символ '#' используется для изображения стен;

- символ 'O' используется для изображения стартовой позиции;

- символ 'X' используется для изображения целевой позиции.

Перед лабиринтом не печатается пустая строка. Пустая строка печатается в конце каждой строки лабиринта, включая последнюю. Список positions содержит пройденные позиции (найденный в лабиринте путь). Они изображаются символом '.' .

 

Функция maze-is-goalвозвращает не NIL, если указанный лабиринт решен, т. е., если стартовая и целевая позиции одинаковы.

(defun maze-is-goal (maze-state)

(let ((maze (second maze-state)))

(and

(= (maze-start-row maze) (maze-goal-row maze))

(= (maze-start-column maze)

(maze-goal-column maze))))

)

 

Функция maze-expandвозвращает список состояний лабиринта, достижимых за одно перемещение. Состояние достижимо, если новая стартовая позиция получается одним перемещением влево, вправо, вверх или вниз относительно начальной стартовой позиции и координаты этой позиции не совпадают с координатами стены.

(defun maze-expand (maze-state)

(let ((maze (second maze-state)))

(labels ((is-empty (row column)

; Возвращает не-NIL если лабиринт не содержит стену
; в указанной позиции (row column)

(not (aref (maze-grid maze) row column)))

(new-maze-if-legal (row column)

; Возвращает состояние лабиринта, соответствующее
; состоянию, достижимому из состояния maze-state
; путем перемещения в новую строку и столбец, или
; NIL, если премещение не допустимо

(and (array-in-bounds-p (maze-grid maze)

row column)

(is-empty row column)

(not (member (list row column)

(first maze-state)

:test #'equal))

(list

;Новая позиция добавляется в начало списка

;позиций

(cons (list row column)

(first maze-state))

; Новый лабиринт такой же как и старый,

; различны только стартовые позиции

(make-maze :start-row row

:start-column column

:goal-row

(maze-goal-row maze)

:goal-column

(maze-goal-column maze)

:grid

(maze-grid maze))))))

(let ((row (maze-start-row maze))

(column (maze-start-column maze)))

(remove nil

; Формируем список достижимых состояний.

; Некоторые элементы могут быть равны NIL,

; если попытки перемещения закончились неудачей

(mapcar #'new-maze-if-legal

(list (1- row)

(1+ row)

row

row)

(list column

column

(1- column)

(1+ column)))) )))

 

)

Примечание: функция labels эквивалентна функции let, но работает с функциями, а не с переменными. Например:

(labels ((factorial (n)

(if (= n 0) 1

(* n (factorial (- n 1)))) ))

(factorial 3) )

Функция maze-solveрешает заданный лабиринт, печатает решение. Если решения не существует, печатает соответствующее сообщение. Эту функцию можно определить следующим образом:

(defun maze-solve

(maze search-strategy tree-searcher)

(format t «Attempting to solve the following

maze:~%»)

(maze-print maze nil)

(terpri)

(let ((solution (funcall search-strategy

(list

(list

(list (maze-start-row maze)

(maze-start-column

maze))) maze)

#'maze-is-goal

#'maze-expand

tree-searcher)))

(if solution

(progn

(format t «Solution:~%»)

(maze-print (second solution)

(first solution))

)

(format t «No solution exists.~%»)) solution))

 

Ниже приведено несколько примеров использования выше перечисленных функций.

Примеры.

>(maze-solve complex-maze #'breadth-first-search

#'iterative-tree-search)

Attempting to solve the following maze:

##########

# # #

## # ### #

# # # #

# ## # #

# ## #####

# # 0

# ## ###

# # ## #

X ########

 

Solution:

##########

# # #

## # ### #

# # # #

# ## # #

# ## #####

# #.......

#...## ###

#.# ## #

..########

(((9 0) (9 1) (8 1) (7 1) (7 2) (7 3) (6 3) (6 4)

(6 5) (6 6) (6 7) (6 8) (6 9))

#S(MAZE START-ROW 9 START-COLUMN 0 GOAL-ROW 9

GOAL-COLUMN 0 GRID

#2A((T T T T T T T T T T)

(T NIL NIL T NIL NIL NIL NIL NIL T)

(T T NIL T NIL T T T NIL T)

(T NIL NIL NIL NIL T NIL T NIL T)

(T NIL T T NIL T NIL NIL NIL T)

(T NIL T T NIL T T T T T)

(T NIL T NIL NIL NIL NIL NIL NIL NIL)

(T NIL NIL NIL T T NIL T T T)

(T NIL T NIL T T NIL NIL NIL T)

(NIL NIL T T T T T T T T))))

 

Ниже представлено несколько лабиринтов, которые Вы можете использовать для тестирования программы:

(defconstant simple-maze

(make-maze :start-row 0

:start-column 0

:goal-row 2

:goal-column 2

:grid #2A((nil nil t)

(nil t t)

(nil nil nil)))

«A very simple maze.»)

 

(defconstant complex-maze

(make-maze :start-row 6

:start-column 9

:goal-row 9

:goal-column 0

:grid #2A(

(t t t t t t t t t t)

(t nil nil t nil nil nil nil nil t)

(t t nil t nil t t t nil t)

(t nil nil nil nil t nil t nil t)

(t nil t t nil t nil nil nil t)

(t nil t t nil t t t t t)

(t nil t nil nil nil nil nil nil nil)

(t nil nil nil t t nil t t t)

(t nil t nil t t nil nil nil t)

(nil nil t t t t t t t t)))

«A more complex maze.»)



<== предыдущая лекция | следующая лекция ==>
Теоретические сведения | Задание на лабораторную работу


Карта сайта Карта сайта укр


Уроки php mysql Программирование

Онлайн система счисления Калькулятор онлайн обычный Инженерный калькулятор онлайн Замена русских букв на английские для вебмастеров Замена русских букв на английские

Аппаратное и программное обеспечение Графика и компьютерная сфера Интегрированная геоинформационная система Интернет Компьютер Комплектующие компьютера Лекции Методы и средства измерений неэлектрических величин Обслуживание компьютерных и периферийных устройств Операционные системы Параллельное программирование Проектирование электронных средств Периферийные устройства Полезные ресурсы для программистов Программы для программистов Статьи для программистов Cтруктура и организация данных


 


Не нашли то, что искали? Google вам в помощь!

 
 

© life-prog.ru При использовании материалов прямая ссылка на сайт обязательна.

Генерация страницы за: 0.053 сек.