Как написать вид условного планирования в прологе?
Я попытался написать код пролога, который может понять студенческую программу, написанную на C#. Сейчас я застрял в процессе распознавания утверждения "если" в студенческой программе. Например: ниже приведен код, который я ожидаю от студента.
int d = int.Parse(Console.ReadLine()); // value d is inputted by user
int s = 0;
if (d>0)
s = 2;
else if (d==0)
s = 1;
else
s = 0;
Я определил цель этого ожидаемого кода как:
goal:-
hasVarName(Vid_s, s),
hasVarName(Vid_d, d),
hasVarValue(Vid_d, Vd),
((not(gt(Vd,0)); hasVarValue(Vid_s, 2)), %eq: [Vd>0] -> [val_s = 2]
((gt(Vd,0); not(eq(Vd,0)); hasVarValue(Vid_s, 1)), %eq: [~(Vd>0)^(Vd=0)] -> [val_s = 1]
((gt(Vd,0); eq(Vd,0); hasVarValue(Vid_s, 0). %eq: [~(Vd>0)^~(Vd=0)] -> [val_s = 0]
Проблема заключается в том, как я могу представить вышеуказанный код студента в прологе фактов и правил, чтобы выяснить, что цель удовлетворяется при любых возможных условиях.
Я пытался изменить первую часть студенческого кода, чтобы она стала похожа на факты, подобные приведенным ниже, но я не знаю, как представить утверждение "если" учащегося как факты / правила в прологе (я думаю, я не должен менять его на пролог "если", верно?)
hasVarName(varID_d, d)
hasVarValue(varID_d, val_d) %it is unknown, so I represent it as symbol 'val_d'
hasVarName(varID_s, s)
hasVarValue(varID_s, 0)
И еще один, в моей цели, когда у меня есть сравнение, такое как gt(Vd,0)
Я думаю, что я не могу использовать пролог больше, чем оператор, ни Vd> 0
ни Vd @> 0
причиной того, что значение в Vd на самом деле является определенным значением, введенным пользователем, но оно представляется как символическое значение (в данном случае это: val_d
).
Примечание: используя вышеуказанную цель, я думаю, что определенная цель будет достигнута, если код студента будет изменен на следующий код.
int d = int.Parse(Console.ReadLine()); // value d is inputted by user
int s = 0;
if (d>0)
s = 2;
else if (d==0)
s = 1;
или же
int d = int.Parse(Console.ReadLine()); // value d is inputted by user
int s = 10; // any random initialization
if (d>0)
{
int x = 2; // unnecessary step, but still Ok.
s = x;
}
else if (d==0)
s = 1;
else
s = 0;
Но опять же, мне нужна помощь / идея, как этот код может быть представлен в прологе как действие / правило / факт для достижения цели.
Любая помощь очень ценится.
Большое спасибо
2 ответа
Я предполагаю, что вы пытались смоделировать if-then-else с помощью импликации, используя следующую логическую идентификацию:
A -> B == ~A v B.
Вместо использования сочетаний последствий проще использовать дизъюнкцию для выбора между ветвями и конъюнкцией вдоль потока управления. Но то, что вы исключаете предыдущие if-условия через отрицание, все еще необходимо.
Возьмите свой пример:
if (d>0)
s = 2;
else if (d==0)
s = 1;
else
s = 0;
Вы можете использовать CLP( *) для моделирования. Добавьте дополнительные переменные, чтобы переменные не переопределялись, но это не проблема в небольшом приведенном фрагменте. В CLP( *) приведенный выше фрагмент становится, я использую CLP(FD) для простоты:
Welcome to SWI-Prolog (Multi-threaded, 64 bits, Version 6.3.0)
Copyright (c) 1990-2012 University of Amsterdam, VU Amsterdam
?- use_module(library(clpfd)).
?- [user].
that_if(D, S) :-
(D #> 0, S #= 2;
D #=< 0, D #= 0, S #= 1;
D #=< 0, D #\= 0, S #= 0)
^D
В приличной системе CLP( *) вы можете произвольно создавать или ограничивать D или S в запросе. Мы получаем, например, уже в CLP(FD):
/* What conditions give result S #= 1 ? */
?- S #= 1, that_if(D, S).
S = 1,
D = 0 .
/* What results give condition D #= 1 */
?- D #= 1, that_if(D, S).
D = 1,
S = 2 ;
false.
/* What conditions give a result S #=< 1 */
?- S #=< 1, that_if(D, S).
S = 1,
D = 0 ;
S = 0,
D in inf.. -1.
/* What results give a condition D #>= 0 */
?- D #>= 0, that_if(D, S).
S = 2,
D in 1..sup ;
D = 0,
S = 1 ;
false.
до свидания
Обычно для реализации языка требуется абстрактное синтаксическое дерево, в котором удобно указывать семантические действия, реализующие конструкции, которые нам разрешено выражать.
Вы, кажется, пропускаете этап построения синтаксического дерева и представляете (вручную?) Промежуточный уровень программы.
Если вы придерживаетесь такого среднего уровня представления, вы можете использовать рекурсивный термин (по сути, абстрактное дерево), например if(Condition, Then, Else)
где каждая переменная это в свою очередь синтаксическое дерево.
В противном случае, для более практического представления (обычно применяемого для императивного языка), используйте понятия базовых блоков (последовательность команд без переходов), а затем меток, чтобы описать поток выполнения.
В результате получается график, и поведение программы определяется "топологией" этого представления.
goal:-
hasVarName(Vid_s, s),
hasVarName(Vid_d, d),
hasVarValue(Vid_d, Vd),
%eq: [Vd>0] -> [val_s = 2]
((not(gt(Vd,0)); hasVarValue(Vid_s, 2), goto(label(0))),
%eq: [~(Vd>0)^(Vd=0)] -> [val_s = 1]
((gt(Vd,0); not(eq(Vd,0)); hasVarValue(Vid_s, 1), goto(label(0))),
%eq: [~(Vd>0)^~(Vd=0)] -> [val_s = 0]
((gt(Vd,0); eq(Vd,0); hasVarValue(Vid_s, 0)), % the goto is useless here...
label(0),
.....
Обратите внимание, что я не обратил никакого внимания на правильное описание вашей программы, просто поместил переходы, чтобы показать эту возможность...
Я думаю, что общая проблема не может быть решена, что эквивалентно проблеме остановки для машины Тьюринга. Для конкретного случая под рукой, без циклов, я бы атаковал проблему, используя абстрактную интерпретацию на AST. Т.е. переводчик, который вычисляет, что интересно.
Если это возможно, зависит от общности ваших целевых программ. Вы должны иметь возможность разделить целочисленный домен для каждой переменной, участвующей в каждой точке условия. Вещи становятся быстро сложными...
В частности, в точке условия IF THEN ELSE попытаться разбить домен. Используя такой подход, пусть Prolog выполнит IF-тестирование обеих ветвей, распространяя значения. Но, как я уже сказал, это не очень легко...