Логическая задача на Prolog: Порядок фигур

      Комментарии к записи Логическая задача на Prolog: Порядок фигур отключены

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

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

    prologgg
    Участник

    Помогите с решением логической задачи.

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

    И нужно ли добавлять такое свойство как номер фигуры?

    DOMAINS
    	тип,цвет = symbol
    	предмет = фигура(тип,цвет)
    	список_предметов = предмет*
    PREDICATES
    
    	nondeterm возможный_тип(тип)
    	nondeterm возможный_цвет(цвет)
            %nondeterm возможный_номер(номер)
            
            имеет_тип(предмет,тип)
            имеет_цвет(предмет,цвет)
           %имеет_номер(предмет,номер)
    	
    	%nondeterm крайний_слева(предмет,предмет,предмет,список_предметов)
    	%nondeterm крайний_справа(список_предметов,предмет,предмет,предмет)
    	%nondeterm положение_на_столе(предмет,предмет,предмет,список_предметов)
    	
    	nondeterm ищем_решение(список_предметов) 
    CLAUSES
           
    %  возможные значения свойств фигур	
    	возможный_тип(треугольник).
    	возможный_тип(ромб).
    	возможный_тип(круг).
    	возможный_тип(квадрат).
    	возможный_цвет(зеленый).
    	возможный_цвет(желтый).
    	возможный_цвет(синий).
    	возможный_цвет(красный).
    	%возможный_номер(первый).
    	%возможный_номер(второй).
    	%возможный_номер(третий).
    	%возможный_номер(четвертый).
    	
    %  извлечение значения конкретного свойства 	
    	имеет_тип(фигура(Точка,_),Тип):- Тип=Точка.
    	имеет_цвет(фигура(_,Черный),Цвет):- Цвет=Черный.
    	%имеет_номер(фигура(_,_,Сотый),Номер):- Номер=Сотый.
    	
    %  определение, как трактовать "положение_на_столе"	
    	%положение_на_столе(A,B,С,[A,B,С,_]).
    	%положение_на_столе(A,B,D,[A,B,_,D]).
    	%положение_на_столе(A,C,D,[A,_,C,D]).
    	%положение_на_столе(B,C,D,[_,B,C,D]).
    	
    	ищем_решение(Фигуры):-
    		возможный_тип(Тип1),
    		возможный_тип(Тип2),
    		возможный_тип(Тип3),
    		возможный_тип(Тип4),
    
    		возможный_цвет(Цвет1),
    		возможный_цвет(Цвет2),
    		возможный_цвет(Цвет3),
    		возможный_цвет(Цвет4),
    		% возможный_номер(Номер1), 		
    		% возможный_номер(Номер2),
    		% возможный_номер(Номер3),
    		% возможный_номер(Номер4),
    
    		not(Тип1=Тип2), not(Цвет1=Цвет2), 
    		%not(Номер1=Номер2),
    		not(Тип1=Тип3),not(Цвет1=Цвет3), 
    		%not(Номер1=Номер3),
    		not(Тип1=Тип4),not(Цвет1=Цвет4), 
    		%not(Номер1=Номер4),
    		not(Тип3=Тип2),not(Цвет3=Цвет2), 
    		%not(Номер3=Номер2),
    		not(Тип4=Тип2),not(Цвет4=Цвет2), 
    		%not(Номер4=Номер2),
    		not(Тип4=Тип3),not(Цвет4=Цвет3), 
    		%not(Номер4=Номер3),
    		
    	        Фигуры = [
    			фигура(Тип1,Цвет1),
    			фигура(Тип2,Цвет2),
    			фигура(Тип3,Цвет3),
    			фигура(Тип4,Цвет4)
    		]. 	
    GOAL
    	ищем_решение(Фигуры).

  • #2835

    Посмотрите пример решения задачи на следование.

    Ваш код можно значительно сократить и упростить. Вместо проверок not(Тип1 = Тип2) и так далее достаточно применить функцию unique, которая завершается успешно только если в списке нет повторяющихся элементов:

    unique([Цвет1, Цает2, Цвет3, Цвет4]),
    unique([Тип1, Тип2, Тип3, Тип4]).

    Чтобы это работало в Visual Prolog , в разделе domains нужно объявить список цветов и список типов:

    типы = тип*
    цвета = цвет*

    Номера фигурам не нужны — для этого достаточно позиции элемента в списке. Функция извлечения свойств — тоже не нужна. Вам нужно применить функцию разделения списка (ее можно использовать также для поиска подсписков). С ее помощью все ограничения из задачи записываются очень легко:

    %% фигура красного цвета лежит между зеленой и синей
    red_shape_chech(Shapes):-
      divide_list(Shapes, [_,[shape(_, green), shape(_, red), shape(_, blue)], _]);
      divide_list(Shapes, [_,[shape(_, blue), shape(_, red), shape(_, green)], _]).

    Мы ищем в списке фигур и цветов подсписок из трех элементов — [зеленый, красный, синий], а если не находим — то ищем [синий, красный, зеленый]. Если не один из подсписков не найден в списке — то вариант размещения фигур и цветов будет отвергнут (запустится поиск других вариантов).

    Аналогично при проверке, что справа от желтой фигуры лежит ромб достаточно проверить в списке наличие нужного подсписка из двух элементов:

    yellow_shape_check(Shapes):-
      divide_list(Shapes, [_,[shape(_, yellow), shape(rhombus, _)], _]).

    Аналогично записываются все остальные условия.

  • #2843

    prologgg
    Участник

    DOMAINS
    	тип,цвет = symbol
    	предмет = фигура(тип,цвет)
    	список_предметов = предмет*
    	типы = тип*
            цвета = цвет*
    
    PREDICATES
    	nondeterm divide_list(список_предметов, список_предметов)
    CLAUSES
    	divide_list(Part, [Part]):-!.
            divide_list(List, [First_Part|Tail]):-
                    append(First_Part, ListPart, List),
                    divide_list(ListPart, Tail).
    

    Подскажите, пожалуйста, почему появляются ошибки.

    Type error: Illegal variable type for this position

    Показывает ошибку в этой строчке:
    divide_list(Part, [Part]):-!.

    Type error: The functor does not belong to the domain

    В этой:
    divide_list(Shapes, [_,[shape(_, green), shape(_, red), shape(_, blue)], _]);

    Я внимательно прочитал информацию по тем ссылкам, который вы оставили, но не смог самостоятельно разобраться.

    • #2844

      Проблема в том, что вторым аргументом функции divide_list является список списков, заданных первым аргументом:
      divide_list(Part, [Part]):-!.
      Если Part — это список_предметов, то [Part] — это список с элементами типа список_предметов.
      Т.е. в раздел domains добавьте:
      список_списков_предметов = список_предметов*
      и в разделе predicates замените тип:
      nondeterm divide_list(список_предметов, список_списков_предметов)

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

      Кстати, я бы не советовал писать код на русском языке, т.к. возможен ряд проблем:

      • вы, наверняка знаете, про отображение символов в виде абракадабры. Это можно исправить сменой шрифта, не всегда. На wine (под linux) это сделать не получается — даже при успешной замене кодировки в редакторе, абракадабра отображается в окне вашей программы после запуска;
      • очень часто встречаются ошибки, когда вместо кириллической буквы «o» напишут латинскую и наоборот. Особенную боль эта ошибка доставляет если случается в разделе domains;
      • аналогично предыдущей проблеме, но еще хуже — если вы копируете код с сайтов и он на кириллице, то иногда символы могут оказаться в разных кодировках (.win1251 и UTF-8). В Visual Prolog найти ошибку при этом вообще нереально, файл надо открывать в другом редакторе — типа kate или gedit.

      Я просто не понимаю зачем создавать себе лишние проблемы с этой кириллицей.

  • #2852

    prologgg
    Участник

    Здравствуйте еще раз. Код на писан на русском так как это требование преподавателя. Использование предиката divide_list тоже не разрешается.
    Подскажите, пожалуйста, как правильно описать условие «фигура красного цвета лежит между зеленой и синей». Ведь красная фигура может лежать как и между зеленой и синей:
    положение_на_столе (фигура(_,зеленый),фигура(_,красный),фигура(_,синий),Фигуры), так и наоборот положение_на_столе (фигура(_,синий),фигура(_,красный),фигура(_,зеленый),Фигуры),. Я пробовал описать это через или

    положение_на_столе (фигура(_,зеленый),фигура(_,красный),фигура(_,синий),Фигуры);
    положение_на_столе (фигура(_,синий),фигура(_,красный),фигура(_,зеленый),Фигуры),
    ,но пролог почему то не замечает второй вариант.
    Тоже самое у нас получается со свойством
    «круг лежит правее треугольника и ромба»,так как круг может лежать правее треугольника и ромба, так и правее ромба и треугольника.
    DOMAINS
    	тип,цвет = symbol
    	предмет = фигура(тип,цвет)
    	список_предметов = предмет*
    	
    	
    PREDICATES
            
    	nondeterm возможный_тип(тип)
    	nondeterm возможный_цвет(цвет)
    	
    	имеет_тип(предмет,тип)
    	имеет_цвет(предмет,цвет)
    	nondeterm положение_на_столе(предмет,предмет,предмет,список_предметов)
    	nondeterm ищем_решение(список_предметов) 
    CLAUSES
    
    %  возможные значения свойств фигур	
    	возможный_тип(треугольник).
    	возможный_тип(ромб).
    	возможный_тип(круг).
    	возможный_тип(квадрат).
    	возможный_цвет(зеленый).
    	возможный_цвет(желтый).
    	возможный_цвет(синий).
    	возможный_цвет(красный).
    	
    	имеет_тип(фигура(Точка,_),Тип):- Тип=Точка.
    	имеет_цвет(фигура(_,Черный),Цвет):- Цвет=Черный.
    	
    	
    	
    	положение_на_столе(A,B,С,[A,B,С,_]).
    	положение_на_столе(A,B,D,[A,B,_,D]).
    	положение_на_столе(A,C,D,[A,_,C,D]).
    	положение_на_столе(B,C,D,[_,B,C,D]).
    
    	
    	ищем_решение(Фигуры):-         /*  Генерация гипотезы    */
    		возможный_тип(Тип1),возможный_тип(Тип2),возможный_тип(Тип3),возможный_тип(Тип4),
    		возможный_цвет(Цвет1),возможный_цвет(Цвет2),возможный_цвет(Цвет3),возможный_цвет(Цвет4),
    		
    		not(Тип1=Тип2), not(Цвет1=Цвет2), 
    		
    		not(Тип1=Тип3),not(Цвет1=Цвет3), 
    	
    		not(Тип1=Тип4),not(Цвет1=Цвет4), 
    		
    		not(Тип3=Тип2),not(Цвет3=Цвет2), 
    		
    		not(Тип4=Тип2),not(Цвет4=Цвет2), 
    		
    		not(Тип4=Тип3),not(Цвет4=Цвет3), 
    		
    		
    	        Фигуры =[фигура(Тип1,Цвет1),фигура(Тип2,Цвет2),фигура(Тип3,Цвет3),фигура(Тип4,Цвет4)],	
      	        	
    		                  /* Проверка гипотезы      */
    	
    	 
    	 
    	 
    	 	 
    	 
    	 	                  
    %  фигура красного цвета лежит между зеленой и синей		                  
      
      
      положение_на_столе (фигура(_,зеленый),фигура(_,красный),фигура(_,синий),Фигуры),
    %  положение_на_столе (фигура(_,синий),фигура(_,красный),фигура(_,зеленый),Фигуры),
       
    %  справа от желтой фигуры лежит ромб
       
       положение_на_столе(фигура(_,желтый),фигура(ромб,_),_,Фигуры),
             	
            		                  
    %  круг лежит правее треугольника и ромба
       
       положение_на_столе(фигура(треугольник,_),фигура(ромб,_),фигура(круг,_),Фигуры),
       %положение_на_столе(фигура(ромб,_),фигура(треугольник,_),фигура(круг,_),Фигуры),
      
      	                  
    %  треугольник лежит не с краю
       положение_на_столе(_,фигура(треугольник,_),_,Фигуры),
      	       
    
    %  фигура синего цвета не лежит рядом с фигурой желтого цвета		
        not(положение_на_столе(фигура(_,желтый),фигура(_,синий),_,Фигуры)),
        not(положение_на_столе(_,фигура(_,синий),фигура(_,желтый),Фигуры)).
    
    GOAL
            
       ищем_решение(Фигура).       
    

  • #2853

    Код на писан на русском так как это требование преподавателя. Использование предиката divide_list тоже не разрешается.

    Перейдите по ссылке с описанием предиката, скопируйте его и переименуйте в «разделение_списка». Я уже написал как решаются все ваши проблемы.

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