Логическая задача про животных

      Комментарии к записи Логическая задача про животных отключены

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

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

    Текст задачи:

    Резвый – это собака. Рекс – это собака. Белка – это кошка. Быстрая – это лошадь. Резвый – черная. Белка – белая. Рекс – рыжая. Быстрая – белая. Домашние животные – это собака или кошка. Животные – это либо лошадь, либо домашние животные. Том владеет тем, кто собака и не черного цвета. Кейт владеет тем, кто либо черного цвета, либо лошадь. Ответить на вопросы: Кто есть кто? Кем владеет Том (указать название, цвет, кличку)? Кем владеет Кейт (указать название, цвет, кличку)?

    Решить требуется на Visual Prolog, но наше решение с небольшими изменениями может быть запущено на любом другом прологе (например SWI Prolog).

    Опишем типы данных:

    domains
      man_d = tom; keyt
      nickname_d = reks; belka; bistraya; rezvii
      animal_d = dog; cat; horse
      color_d = black; white; red 
      
      struct_animal_d = struct_animal(nickname_d, animal_d, color_d)
      struct_owner_d = struct_owner(man_d, struct_animal_d)
      
      animals_d = struct_animal_d*
      owners_d = struct_owner_d*

    Типы в SWI Prolog помогают избежать ошибок. Например, если в программе мы ошибемся и напишем вместо rezvii слово rezvi, то компилятор сообщит нам об этом. В SWI Prolog нестрогая типизация, поэтому контроль типов отсутствует – мы узнаем об ошибке только когда программа вернет нам некорректный результат.

    В секции predicates опишем прототипы функций:

    predicates
      nondeterm pet(animal_d)
      nondeterm animal(animal_d)
      nondeterm animal_option(struct_animal_d)
      nondeterm check(man_d, struct_animal_d)
      nondeterm owners(owners_d) 

    Домашние животные описываются предикатом pet:

      pet(dog).
      pet(cat).

    Правило проверки животных завершается успешно если переданный вид является домашним животным или (в прологе обозначается точкой, см. семантику пролог-программ) – лошадью:

      animal(Animal):-
      	pet(Animal).
      animal(horse).

    В предикате animal_option записываются остальные факты о животных, имеющиеся в задаче:

      animal_option(struct_animal(rezvii, dog, black)).
      animal_option(struct_animal(reks, dog, red)).
      animal_option(struct_animal(belka, cat, white)).
      animal_option(struct_animal(bistraya, horse, white)).

    Функция check выполняет проверку соответствия животного и его хозяина:

      check(keyt, struct_animal(_, _, black)).
      check(keyt, struct_animal(_, horse, _)).
      check(tom, struct_animal(_, dog, Color)):-
      	NOT(Color = black).

    Для использования этого правила надо передать имя хозяина и имя его животного, тогда выполнится проверка что животное Кейт черного цвета или (опять же обозначается точкой) является лошадью.

    Функция owners возвращает список из двух элементов, каждый из которых содержит информацию о хозяине и животном:

     owners([
      	struct_owner(keyt, KeytAnimal),
      	struct_owner(tom, TomAnimal)
      ]):-
      	animal_option(KeytAnimal),
      	animal_option(TomAnimal),
      	NOT(KeytAnimal = TomAnimal),
      	
      	check(keyt, KeytAnimal),
      	check(tom, TomAnimal).

    Задача решается методом генерации гипотезы, т.е. сначала мы генерируем все возможные варианты решения, а затем выполняем проверку. Проверка содержит как проверку высказываний, так и того, что животные не повторяются.

    Для поиска всех решений можно использовать стандартный предикат findall:

    goal 
      findall(Animal, animal_option(Animal), Animals),
      owners(Owners).

    Результат работы программы:
    pets-logical-task-prolog

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