Попытка диверсии — найти преступника.

      Комментарии к записи Попытка диверсии — найти преступника. отключены

В этой теме 1 ответ, 2 участника, последнее обновление  Васильев Владимир Сергеевич 1 год, 5 мес. назад.

  • Автор
    Сообщения
  • #2656

    zageul
    Участник

    Необходимо решить задачу на Visual Prolog 5.2:

    Попытка диверсии

    На планету Дранак прилетел космический корабль, но не все местные жители этому обрадовались.
    Ночью неизвестный преступник прокрался к кораблю и хотел сломать систему подачи воздуха.
    На следующий день задержали троих подозреваемых. Каждый из них высказался три раза.
    Мы знаем, что все высказывания одного из подозреваемых — правда,
    все высказывания второго — ложь, а про то, насколько лжет третий, ничего не известно.
    Тем не менее преступника можно найти. Кто это?

    А: 1. Это сделал не я.
    2. Я всегда говорю правду.
    3. Мне не нравятся космические полеты.

    Б: 1. Это сделал не я.
    2. Я всегда говорю неправду.
    3. Мне не нравятся пришельцы из космоса.

    В: 1. Это сделал не я.
    2. Только одно из моих высказываний ложно.
    3. Мне нравятся гости из космоса.

    Получился такой код:

    DOMAINS
    имя = symbol
    номер = integer
    PREDICATES
    nondeterm возможное_имя(имя)
    nondeterm сказал (имя, номер)
    nondeterm является_преступником (имя) 
    nondeterm говорит_правду (имя,номер)
    nondeterm говорит_ложь (имя,номер)
    nondeterm говорит_неизвестно (имя)
    CLAUSES
    возможное_имя(а).
    возможное_имя(б).
    возможное_имя(в).
    % Высказывания
    % Это сделал не я.
    сказал (а,1):-
    not(является_преступником(а)).
    % Мне не нравятся космические полеты.	
    сказал (а,2):-
    является_преступником(а).
    % Я всегда говорю правду.	
    сказал (а,3):-
    сказал (а,3), сказал (а,1), сказал (а,2).
    % Это сделал не я.	
    сказал (б,1):-
    not(является_преступником(б)).
    %  Мне не нравятся пришельцы из космоса.	
    сказал (б,2):-
    является_преступником(б).
    % Я всегда говорю неправду.	
    сказал (б,3):-
    not(сказал (б,3)), not(сказал (б,1)), not(сказал (б,2)).
    % Это сделал не я.	
    сказал (в,1):-
    not(является_преступником(в)).
    % Мне нравятся гости из космоса.	
    сказал (в,2):-
    not(является_преступником(в)).
    % Только одно из моих высказываний ложно.	
    сказал (в,3):-
    not(сказал (в,1)), сказал (в,2), сказал (в,3);
    сказал (в,1), not(сказал (в,2)), сказал (в,3);
    сказал (в,1), сказал (в,2), not(сказал (в,3)).
    % Проверка правдивости высказывания в зависимости от того, кем является персонаж
    % все высказывания одного из подозреваемых - правда
    говорит_правду(Кто_сказал,Номер_высказывания):-
    сказал (Кто_сказал, Номер_высказывания).
    % все высказывания второго - ложь 
    говорит_ложь(Кто_сказал,Номер_высказывания):-
    not(сказал (Кто_сказал, Номер_высказывания)).
    % насколько лжет третий, ничего не известно.
    говорит_неизвестно(Кто_сказал):-
    сказал (Кто_сказал,1), сказал (Кто_сказал,2), сказал (Кто_сказал,3);
    сказал (Кто_сказал,1), сказал (Кто_сказал,2), not(сказал (Кто_сказал,3));
    сказал (Кто_сказал,1), not(сказал (Кто_сказал,2)), сказал (Кто_сказал,3);
    сказал (Кто_сказал,1), not(сказал (Кто_сказал,2)), not(сказал (Кто_сказал,3));
    not(сказал (Кто_сказал,1)), сказал (Кто_сказал,2), сказал (Кто_сказал,3);
    not(сказал (Кто_сказал,1)), сказал (Кто_сказал,2), not(сказал (Кто_сказал,3));
    not(сказал (Кто_сказал,1)), not(сказал (Кто_сказал,2)), сказал (Кто_сказал,3);
    not(сказал (Кто_сказал,1)), not(сказал (Кто_сказал,2)), not(сказал (Кто_сказал,3)).
    % Поиск ответа задачи
    является_преступником(Преступник):-
    % Генерация гипотезы.
    возможное_имя(П), 
    возможное_имя(Л), not(Л=П),
    возможное_имя(Н), not(Н=П), not(Н=Л),			
    % Проверка высказываний
    говорит_правду(П,1),
    говорит_правду(П,2),
    говорит_правду(П,3),
    говорит_ложь(Л,1),
    говорит_ложь(Л,2),
    говорит_ложь(Л,3),
    говорит_неизвестно(Н).	
    GOAL
    является_преступником(Преступник).

    При попытке решения выплывает «PROGRAM ERROR. 1010», подскажите пожалуйста с чем связана ошибка и как можно ее исправить.

  • #2657

    Ошибка «PROGRAM ERROR. 1010» говорит о переполнении стека, чаще всего это возникает при зацикливании (вечной рекурсии).
    Ваш код я не смог понять, так правило является_преступником принимает в качестве аргумента переменную Преступник, но в коде правила она не используется, т.е. при любом раскладе функция не вернет ничего более полезного чем неинициализированную переменную.

    Я не знаю точно в чем у вас ошибка, но зацикливание может быть например тут:

    сказал (в,3):-
    not(сказал (в,1)), сказал (в,2), сказал (в,3);
    сказал (в,1), not(сказал (в,2)), сказал (в,3);
    сказал (в,1), сказал (в,2), not(сказал (в,3)).

    Так как чтобы вычислить правило вы вызываете это же правило с точно таким же набором аргументов. Очевидно, выполнение зациклится, а т.к. используется рекурсия (т.е. вызовы функции, сохраняющие аргументы при каждом вызове в стек) — переполнится стек.

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

Для ответа в этой теме необходимо авторизоваться.