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

Экспертная система. Логическая задача. Фейерверк

< Лекция 14 || Лекция 15: 123 || Лекция 16 >

15.2. Головоломка Эйнштейна

Знаменитая головоломка Эйнштейна формулируется следующим образом.

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

  • англичанин живет в красном доме;
  • у испанца есть собака;
  • кофе пьют в зеленом доме;
  • украинец пьет чай;
  • зеленый дом — первый по правую руку от дома цвета слоновой кости;
  • курильщик "Winston" держит улиток;
  • сигареты "Kool" курят в желтом доме;
  • молоко пьют в среднем доме;
  • норвежец живет в крайнем слева доме;
  • мужчина, курящий "Chesterfield", живет в доме, соседнем с домом мужчины, у которого есть лиса;
  • сигареты "Kool" курят в доме, соседнем с тем, где имеется лошадь;
  • мужчина, предпочитающий "Lucky Strike", пьет апельсиновый сок;
  • японец курит сигареты "Parliament";
  • норвежец живет в доме рядом с голубым домом;
  • у одного из мужчин есть зебра;
  • один из мужчин пьет воду.

Определите для каждого дома его цвет, а также национальность, любимый напиток, марку сигарет и домашнее животное хозяина [9].

Ниже приводится решение задачи методом "образовать и проверить". Сначала создается список, состоящий из пяти пустых структур, соответствующих пяти домам. Этот список постепенно заполняется в соответствии с условиями, приведенными в задаче: выбирается произвольным образом одна или две структуры (они берутся по очереди), в зависимости от условия, и делается попытка вставить в нее или в них значения из этого условия. Если этого сделать не удается, то делается откат.

open core, console, list

constants
    empty : symbol = "".
 
domains    % описание дома
    house = h(symbol Colour, symbol Nationality, symbol Pet, 
        symbol Drink, symbol Cigarette).

class predicates
    colour: (house, symbol Colour) -> house determ.
    nationality: (house, symbol Nationality) -> house determ.
    pet: (house, symbol Pet) -> house determ.
    drink: (house, symbol Drink) -> house determ.
    cigarette: (house, symbol Cigarette) -> house determ.
    unif: (symbol, symbol) determ.
    leftmost: (house [out], positive [out], house*) determ.
    middle: (house [out], positive [out], house*).
    next: (house, positive, house, positive, house*) 
        nondeterm (o,o,o,o,i).
    right: (house, positive, house, positive, house*) 
        nondeterm (o,o,o,o,i).
    right: (house, positive, positive, house, positive, positive, house*) 
        nondeterm (o,i,o,o,i,o,i). 
    solve: () -> house* nondeterm.
clauses
    colour(h(Cl, N, P, D, S), C) = h(C, N, P, D, S):- 
        unif(Cl, C).
    nationality(h(C, Nt, P, D, S), N) = h(C, N, P, D, S):-
        unif(Nt, N).
    pet(h(C, N, Pt, D, S), P) = h(C, N, P, D, S):-
        unif(Pt, P).
    drink(h(C, N, P, Dr, S), D) = h(C, N, P, D, S):-
        unif(Dr, D).
    cigarette(h(C, N, P, D, Sg), S) = h(C, N, P, D, S):-
        unif(Sg, S).

    unif(empty, _):- !.
    unif(X, X).

    % крайний слева дом имеет номер 0 и стоит первым в списке
    leftmost(X, 0, [X | _]).
    % средний дом находится в середине списка
    middle(nth(I, L), I, L):-
        I = length(L) div 2.
    % пары соседних домов, где дом B находится справа от дома A
    right(A, I, B, J, L):-
        right(A, 0, I, B, 1, J, L).

    right(A, I, I, B, J, J, [A, B | _]).
    right(A, C1, I, B, C2, J, [_ | L]):-
        right(A, C1 + 1, I, B, C2 + 1, J, L).
    % пары соседних домов
    next(A, Na, B, Nb, Houses):-
        right(A, Na, B, Nb, Houses).
    next(A, Na, B, Nb, Houses):-
        right(B, Nb, A, Na, Houses).    

    solve() = Houses20:- 
        Houses = [h(empty, empty, empty, empty, empty) ||
                            _ = std::fromTo(0, 4)],
    % англичанин живет в красном доме
        memberIndex_nd(H1, C1, Houses),
        setNth(C1, Houses, 
            colour(nationality(H1, "Englishman"), "red"), Houses1),
    % у испанца есть собака
        memberIndex_nd(H2, C2, Houses1),
        setNth(C2, Houses1, pet(nationality(H2, "Spaniard"), "dog"),
                Houses2),
    % кофе пьют в зеленом доме
        memberIndex_nd(H3, C3, Houses2),
        setNth(C3, Houses2, drink(colour(H3, "green"), "coffee"), 
                Houses3),
    % украинец пьет чай
        memberIndex_nd(H4, C4, Houses3),
        setNth(C4, Houses3, drink(nationality(H4, "Ukrainian"), "tea"),
                Houses4),
    % зеленый дом – первый справа от дома цвета слоновой кости
        right(H5, C5, H6, C6, Houses4), 
        setNth(C5, Houses4, colour(H5, "ivory"), Houses5),
        setNth(C6, Houses5, colour(H6, "green"), Houses6),
    % курильщик "Winston" держит улиток
        memberIndex_nd(H7, C7, Houses6),
        setNth(C7, Houses6, pet(cigarette(H7, "Winston"), "snails"),
                Houses7),
    % сигареты "Kool" курят в жёлтом доме
        memberIndex_nd(H8, C8, Houses7),
        setNth(C8, Houses7, colour(cigarette(H8, "Kool"), "yellow"), 
            Houses8),
    % молоко пьют в среднем доме
        middle(H9, C9, Houses8), 
        setNth(C9, Houses8, drink(H9, "milk"), Houses9),
    % норвежец живет в крайнем слева доме
        leftmost(H10, C10, Houses9), 
        setNth(C10, Houses9, nationality(H10, "Norwegian"), 
            Houses10),
    % курящий "Chesterfield", живет по соседству с лисой 
        next(H11, C11, H12, C12, Houses10), 
        setNth(C11, Houses10, cigarette(H11, "Chesterfield"), 
            Houses11),
        setNth(C12, Houses11, pet(H12, "fox"), Houses12),
    % "Kool" курят в доме, соседнем с домом, где имеется лошадь
        next(H13, C13, H14, C14, Houses12), 
        setNth(C13, Houses12, cigarette(H13, "Kool"), Houses13),
        setNth(C14, Houses13, pet(H14, "horse"), Houses14),
    % предпочитающий "Lucky Strike" пьет апельсиновый сок
        memberIndex_nd(H15, C15, Houses14),
        setNth(C15, Houses14, drink(cigarette(H15, "Lucky Strike"), 
                                                "orange juice"), Houses15),
    % японец курит сигареты "Parliament"
        memberIndex_nd(H16, C16, Houses15),
        setNth(C16, Houses15, cigarette(nationality(H16, "Japanese"),
                                                        "Parliament"), Houses16),
    % норвежец живет в доме рядом с голубым домом
        next(H17, C17, H18, C18, Houses16),
        setNth(C17, Houses16, nationality(H17, "Norwegian"), 
            Houses17),
        setNth(C18, Houses17, colour(H18, "blue"), Houses18),
    % у одного из мужчин есть зебра
        memberIndex_nd(H19, C19, Houses18),
        setNth(C19, Houses18, pet(H19, "zebra"), Houses19),
    % один из мужчин пьет воду
        memberIndex_nd(H20, C20, Houses19),
        setNth(C20, Houses19, drink(H20, "water"), Houses20).

    run():-
        Houses = solve(),
            forAll(Houses, {(h(C, N, P, D, S)):- 
                writef("%-10%-14%-10%-16%\n", C, N, P, D, S)}), 
        fail;
        _ = readLine().
Пример 15.3. Решение головоломки Эйнштейна
< Лекция 14 || Лекция 15: 123 || Лекция 16 >
Жаныл Айкын
Жаныл Айкын
Rustam Inatov
Rustam Inatov

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

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

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