Это вопрос
найти значение А.
inverse([],[]).
inverse([H|T],D) :-
inverse(T,Z),
append(Z,[H],D).
append([],X,X).
append([X|L],M,[X|N]) :-
append(L,M,N).
Вот ответ:
Пожалуйста, помогите мне понять это!
Извини, в следующий раз буду осторожен.
Я не знаю, как перевести изображение в код.
Просто я впервые делаю упражнение по прологу, и я не знал, с чего начать.
I don't know how to translate an image to code
. Не беспокойся об этом. Вы новичок в Prolog и новичок в StackOverflow, и, как я отметил в своем ответе, исходный код у вас нестандартный.
Пожалуйста, проверьте "Какой сайт?" на предмет общих проблем. Stack Overflow - это не учебник или справочный сайт.
@Prune Вопрос действительно не по теме для вопроса Prolog здесь. Что делает это сложнее, чем большинство, так это то, что, как отмечает ОП, профессор старый, и это ясно видно в примере кода. Я видел подобное Прологу только в 70-х и 80-х годах или в книгах, сочетающих математику и логику. Я не использую форматирование трассировки.
Я не знаю, как перевести изображение в код. Хорошо, хорошо, я знаю, что мне не следует задавать себе вопросы в StackOverflow, я больше не буду этого делать. Guy Coder, вы очень мне помогаете, но я думаю, что мы не должны заканчивать эту тему здесь для сообщества.
«Stack Overflow - это не учебник или справочный сайт». Мне очень жаль.
чтобы преобразовать изображение в код, вы можете просто ввести вручную код, который вы видите на изображении. Если вы видите там какие-то символы, отличные от ASCII, вы можете изобрести что-нибудь другое, чтобы использовать вместо этого символа, и объясните это в комментариях. :)
@WillNess FYI. Когда мне нужно вставить в документ специальные символы, а редактор не поддерживает опцию расширенного поиска символов, я использую Shapecatcher. С его помощью вы рисуете символ, а затем он возвращает вам символ, имя и даже код Unicode для него. Как только вы воспользуетесь им несколько раз, вы больше не боитесь использовать специальные уставы, только плохие редакторы. Приятно то, что как только вы часто находите нужный персонаж, это просто вырезание и вставка, чтобы вставить его в свой документ.
Изображения кода Пролога, которые вы опубликовали, показывают какой-то необычный или очень старый Пролог, в частности, для списка, использование [H:T]
теперь выполняется как [H|T]
, обратите внимание на изменение с :
на |
, а <=
более распространен как :-
.
Чтобы понять код Пролога, проще начать снизу вверх. Я не буду рассматривать здесь объединение или обратная цепочка, поскольку для перехода к такому уровню детализации потребуются главы, которые стоит здесь.
Первый предикат, который нужно понять, - это append / 3. Обычно вы никогда не видите данный код для добавления, поскольку это встроенный предикат, но здесь он указан.
В приложении / 3 есть три параметра, все из которых являются списком. Первые два складываются вместе, образуя третье.
?- append_01([],[],R).
R = [].
?- append_01([a],[],R).
R = [a].
?- append_01([],[a],R).
R = [a].
?- append_01([a],[b],R).
R = [a, b].
но предикаты Пролога могут иметь другие операции режимы, которые могут связывать значения с тем, что считалось бы входными параметрами в других языках программирования, например
?- append(X,[b],[a,b]).
X = [a] ;
false.
?- append_01([a],Y,[a,b]).
Y = [b].
?- append(X,Y,[a,b]).
X = [] , Y = [a, b] ;
X = [a] , Y = [b] ;
X = [a, b], Y = [] ;
false.
или может использоваться просто для проверки аргументов
?- append([a],[b],[a,b]).
true.
?- append([a],[c],[a,b]).
false.
Далее идет предикат обратный / 2, который в Прологе более известен как обратный / 2, и здесь снова приводится исходный код.
Это просто берет один список и меняет его, например
?- inverse([],X).
X = [].
?- inverse([a],X).
X = [a].
?- inverse([a,b],X).
X = [b, a].
однако эта версия исходного кода не работает в других режимах, например.
?- inverse(X,[]).
X = [] ;
Action (h for help) ? abort
% Execution Aborted
но это не имеет значения, чтобы ответить на вопрос.
Следующая часть того, что вы опубликовали, - это след выполнения запроса.
?- inverse([[1,2,3],[5,4]],A).
Чтобы использовать трассировку в вашем коде, поскольку для append / 3 есть встроенный предикат, мне пришлось переименовать предикат. Вот код, который я использовал.
inverse([],[]).
inverse([H|T],D) :-
inverse(T,Z),
append_01(Z,[H],D).
append_01([],X,X).
append_01([X|L],M,[X|N]) :-
append_01(L,M,N).
Использование SWI-Prolog
установить след
?- visible(+all),leash(-all).
начать трассировку
trace.
выполнить запрос
[trace] ?- inverse([[1,2,3],[5,4]],A).
возвращается
Call: (8) inverse([[1, 2, 3], [5, 4]], _7548)
Unify: (8) inverse([[1, 2, 3], [5, 4]], _7548)
Call: (9) inverse([[5, 4]], _7794)
Unify: (9) inverse([[5, 4]], _7794)
Call: (10) inverse([], _7794)
Unify: (10) inverse([], [])
Exit: (10) inverse([], [])
Call: (10) append_01([], [[5, 4]], _7802)
Unify: (10) append_01([], [[5, 4]], [[5, 4]])
Exit: (10) append_01([], [[5, 4]], [[5, 4]])
Exit: (9) inverse([[5, 4]], [[5, 4]])
Call: (9) append_01([[5, 4]], [[1, 2, 3]], _7548)
Unify: (9) append_01([[5, 4]], [[1, 2, 3]], [[5, 4]|_7792])
Call: (10) append_01([], [[1, 2, 3]], _7792)
Unify: (10) append_01([], [[1, 2, 3]], [[1, 2, 3]])
Exit: (10) append_01([], [[1, 2, 3]], [[1, 2, 3]])
Exit: (9) append_01([[5, 4]], [[1, 2, 3]], [[5, 4], [1, 2, 3]])
Exit: (8) inverse([[1, 2, 3], [5, 4]], [[5, 4], [1, 2, 3]])
A = [[5, 4], [1, 2, 3]].
Я не буду объяснять детали трассировки, поскольку другие вопросы и ответы SO делают тот.
Опубликованная вами трассировка также содержит больше деталей, чем сгенерированная с помощью trace
, например привязки (θ).
Чтобы увидеть привязки, используйте gtrace / 0
?- gtrace.
% The graphical front-end will be used for subsequent tracing
true.
затем выполните запрос
[trace]?- inverse([[1,2,3],[5,4]],A).
и нажмите пробел для перехода к одному шагу. Вам придется поэкспериментировать с ним, чтобы узнать, как он работает; AFAIK нет опубликованной документации о том, как его использовать.
Из комментария OP:
There are some replacements from letters to numbers and theta symbol that make me hard to understand.
Хотя привязки (θ) более специфичны для логические языки, числа также видны в функциональные языки на основе стека, см. Индекс Де Брёйна. Кроме того, вместо того, чтобы писать привязки с использованием вертикального разделителя строк (---), я предпочитаю использовать (↦), как показано на рисунке здесь.
Строки 1-4 - это снова заявленный исходный код.
Обычно при трассировке цель состоит в том, чтобы получить древовидную структуру выполнений (вызовов), но с этими строками, если вы не знаете, как работает Prolog, действительно трудно увидеть, что существует древовидная структура.
Линии с черными черточками предназначены для того, чтобы помочь понять, что происходит, но если вы просто проследите за ходом выполнения (вызовов), то вы, как и я, можете обнаружить, что они вызывают путаницу и могут быть проигнорированы.
Как вы отметили в комментариях, Res(_,_)
ссылается на предыдущие строки трассировки. Таким образом, Res (5,2) в строке 6 можно прочитать как строку 6, которая является результатом вызова из строки 5, который затем вызывает строку 2.
Унификации или привязки (θ) показаны как наборы. Я не совсем уверен, что обозначают номера суперсценария и субсценария, но они явно связаны с индексами Де Брёйна. Вам нужно будет попросить своего учителя объяснить супер- и вспомогательные сценарии.
После нескольких попыток объяснить это простым текстом, я наконец прибег к использованию Microsoft Visio, чтобы сделать это в виде графического дерева, что было намного проще, быстрее и точнее.
Несмотря на то, что в этом не было необходимости, я добавил вывод трассировки линии из SWI-Prolog в изображение, а затем поместил только строки вызова в соответствующие места в дереве, так что, если вы хотите сопоставить два, вы могли. Я сделал это для себя в качестве проверки, чтобы убедиться, что это правильно.
Я не удивлюсь, если будет несколько опечаток, так как мне приходилось переделывать части много раз, чтобы облегчить понимание. Надеюсь, я достиг этой цели.
Мой учитель попросил меня представить мое упражнение как второе изображение, которое я опубликовал. И есть некоторые шаги, которые я не понимаю.
@ MaiHoàngNam Обычно я прошу вас задать другой вопрос, так как в StackOverflow вы задаете вопрос и получаете ответ. Это не должно превращаться в обсуждения. Я помогу вам понять одну или две конкретные вещи, но если вы спросите многих, я потребую, чтобы вы начали новый пост (вопрос).
@ MaiHoàngNam Какой конкретный шаг вы не понимаете?
Есть некоторые замены букв на числа и тета-символ, из-за которых мне трудно понять, что имел в виду мой учитель.
Он старый учитель, и он учит нас делать домашние задания по старому методу.
Я могу понять, что вы мне объяснили, но я не могу отправить это как домашнее задание своему учителю. знак равно
There are some replacements from letters to numbers and theta symbol that make me hard to understand
Я добавлю к ответу. Это займет несколько минут.
Да, я думаю, что вы профессор Prolog xD, и вы очень дружны с новым участником.
Мой вызов учителя ------ обратный отрицателен обратному, RES (5, 2) представлен для соединения шагов 5 и 2.
Я говорю об инверсии с линией на голове, которую вы захватили.
Думаю, твоего ответа мне достаточно. Я просто хочу знать основы Пролога к экзамену и поблагодарить вас за то, что помогли мне это понять.
Мой учитель сказал нам понимать, что делает компьютер с Prolog, а не как работает программа.
@ MaiHoàngNam Я закончил с моим ответом. Надеюсь, мне никогда больше не придется смотреть на трассировку, сделанную в этом формате.
Я понимал, как работает Пролог, но мой учитель математики заставил нас решать его с помощью математической терминологии. К счастью, мне удалось решить эту проблему с помощью разрешения «отрицательного предложения» (мой учитель назвал это так). Мой учитель хотел, чтобы ученики поняли, как машина работает с Прологом, но в форме отрицательного доказательства (вверху) это немного противоположно тому, что вы мне объяснили. XD
Вы понимаете, как работает унификация?