Опубликован: 12.02.2014 | Доступ: свободный | Студентов: 920 / 238 | Длительность: 11:22:00
Специальности: Программист
Лекция 13:

Поиск в пространстве состояний

< Лекция 12 || Лекция 13: 123 || Лекция 14 >
Аннотация: Лекция посвящена решению задач при помощи графа пространства состояний. Пространство состояний описывается в виде множества состояний – вершин графа, множества переходов от состояния к состоянию – дуг графа, множества начальных состояний и множества конечных состояний. Решение задачи представляется в виде пути на графе пространства состояний, соединяющего начальное состояние с конечным. Если пространство состояний задачи невелико, то будут находиться все оптимальные решения с помощью поиска в глубину. В задачах с большим пространством состояний будет вычисляться только одно оптимальное решение посредством поиска в ширину. К задачам применяются универсальные решатели. Состояния в разных задачах могут принадлежать различным доменам. Для запоминания наилучших среди найденных решений используется "изменяемая переменная" varM. Компилятор сам находит нужные типы. Версия Visual Prolog 7.5, еще не опубликована. Ее публикация планируется в 2014 году, но точная дата пока не известна. Сейчас всем доступна версия Visual Prolog 7.4.

Настоящая глава посвящена решению задач при помощи графа пространства состояний. Пространство состояний описывается в виде множества состояний — вершин графа, множества переходов от состояния к состоянию — дуг графа, множества начальных состояний и множества конечных состояний. Решение задачи представляется в виде пути на графе пространства состояний, соединяющего начальное состояние с конечным.

Если пространство состояний задачи невелико, то будут находиться все оптимальные решения с помощью поиска в глубину. В задачах с большим пространством состояний будет вычисляться только одно оптимальное решение посредством поиска в ширину.

К задачам применяются универсальные решатели. Состояния в разных задачах могут принадлежать различным доменам. Для запоминания наилучших среди найденных решений используется "изменяемая переменная" varM. Компилятор сам находит нужные типы.

13.1. Поиск в глубину в пространстве состояний

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

Задача о волке, козе и капусте заключается в следующем (Алкуин, XIII в.). Хозяин с волком, козой и грудой кочанов капусты должен перебраться через реку с левого берега на правый, имея в распоряжении маленькую лодку. В эту лодку, кроме хозяина, может поместиться только что-то одно — либо волк, либо коза, либо капуста. Нельзя оставлять без присмотра волка с козой, а козу с капустой. Как следует организовать переправу?

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

Для решения задач, как и ранее, создается консольный проект. В этом проекте создается модуль depth. В этот модуль следует поместить универсальный решатель, который использует поиск в глубину (листинги 13.113.2)1В листинге 13.2 строку из версии Visual Prolog 7.5 V = varM::new([]), в версии Visual Prolog 7.4 нужно заменить строкой V = varM{tuple{State*, string*}*}::new([]),.

domains
    move{State} = (State, string [out]) -> State nondeterm.

predicates
    depthSearch: (move{State}, State, State, positive [out])
        -> tuple{State*, string*} nondeterm.
Пример 13.1. Декларация класса depth
    open core, list

class facts
    minweight : positive := 2^30.

class predicates
    depthSearch: (move{State}, State, State, tuple{State*, string*},
        positive, positive [out]) -> tuple{State*, string*} nondeterm.
clauses
    depthSearch(Move, Start, Goal, minweight) = 
            tuple(reverse(Path), reverse(Moves)):-
        minweight := 2^30,
        V = varM::new([]),
        foreach tuple(P, Ms) = 
            depthSearch(Move, Start, Goal, tuple([Start], []), 0, N) 
        do
            if N > minweight then succeed()
            elseif N < minweight then 
                V:value := [tuple(P, Ms)], minweight := N
            else V:value := [tuple(P, Ms) | V:value]
            end if
        end foreach,
        tuple(Path, Moves) = getMember_nd(V:value).

    depthSearch(_, Goal, Goal, Path, N, N) = Path:- !.
    depthSearch(Move, State, Goal, tuple(Path, Moves), C, N) =
        depthSearch(Move, NextState, Goal, tuple([NextState | Path],
            [Str | Moves]), C + 1, N):-
        C < minweight,
        NextState = Move(State, Str),
        not(isMember(NextState, Path)).
Пример 13.2. Имплементация класса depth

Далее, как обычно, создаются модули для примеров.

    open core, console, list, depth

class facts
    n : positive := 0.

domains
    wstate = tuple(loc BoatLoc, string* LeftSide, string* RightSide).
    loc = left; right.

class predicates
    wmove : move{wstate}.
    unsafestate : (string*) determ.
    wmoveFromTo: (positive, string*, string*, string* [out],
        string* [out], string* [out]) nondeterm.
    subset : (positive, A*, A* [out], A* [out]) nondeterm.
    f: (string*) -> string.
clauses
    wmoveFromTo(K, FromBef, ToBefore, FromAfter, ToAfter, Boat):-
        subset(K, FromBef, Boat, FromAfter),
        not(unsafestate(FromAfter)),
        ToAfter = sort(append(Boat, ToBefore)).

    wmove(tuple(left, L, R), Str) = tuple(right, L1, R1):-
        wmoveFromTo(1, L, R, L1, R1, B),
        Str = string::format("farmer% moves from left to right", f(B)).
    wmove(tuple(right, L, R), Str) = tuple(left, L1, R1):-
        K = std::fromTo(0, 1),
        wmoveFromTo(K, R, L, R1, L1, B),
        Str = string::format("farmer% moves from right to left", f(B)).

    f([S]) = string::format(" with %", S):- !.
    f(_) = "".

    unsafestate(L):-
        L = [_, _ | _],
        isMember("goat", L).

    subset(0, L, [], L):- !.
    subset(K, [A | L], [A | L1], L2):-
        subset(K - 1, L, L1, L2).
    subset(K, [A | L], L1, [A | L2]):-
        subset(K, L, L1, L2).

    run():-
        L = sort(["wolf", "goat", "cabbage"]),
        Start = tuple(left, L, []),
        Goal = tuple(right, [], L),
        tuple([S0 | P], Moves) = depthSearch(wmove, Start, Goal, _W),
            V = varM::new(1),
            n := n + 1,
            write("\t", S0), nl,
            forAll(zip(P, Moves), {(tuple(X, S)):-
                writef("%. %\n\t%\n", V:value, S, X), 
                V:value := V:value + 1}), nl,
         fail;
         write("\nвсего - ", n),
        _ = readLine().
Пример 13.3. Задача о волке, козе и капусте. Модуль ex1
< Лекция 12 || Лекция 13: 123 || Лекция 14 >
Жаныл Айкын
Жаныл Айкын
Rustam Inatov
Rustam Inatov

Доброго времени суток, подскажите пожалуйста, visual prolog examples, pie, vip7.5 - это все, где я могу скачать? (в смысле) может быть на сайте есть какой-то архив? Увы я не нашел его.

Подскажите, пожалуйста.

С уважением, Рустам.