Prolog:如何验证用户输入?
Prolog: How to Verify User Input?
我是 Prolog 的新手,正在尝试实现教科书中的示例。我已经能够让示例正常工作(通过以前的 Stack Overflow 帖子的明确帮助!),但现在它要求我验证用户输入:"Modify the given decision tree program, so that when the user responds to a question with an illegal answer, the system will ask him/her to reenter an answer which is among the specified choices."
在下面的程序中,对于婚姻状况,决策树中考虑的指定唯一选项是 "single" 或 "married." 如果您输入任何其他内容,目标是让您重新输入您的决定。
这对我不起作用。我的代码如下:
:-dynamic income/2.
:-dynamic marital_status/2.
:-dynamic mortgage/2.
:-dynamic age/2.
marital_status(joe,married).
income(joe,60000).
mortgage(joe,20000).
age(joe,45).
main(X,Z):-var(X), write('what is your name?'),read(X), invest(X,Z),!.
main(X,Z):-invest(X,Z),!.
ask_marital_status(X,Y):-marital_status(X,Y).
ask_marital_status(X,Y):-not(marital_status(X,Y)), write('what is your marital status: married or single?'), read(Y), nl, asserta(marital_status(X,Y)).
ask_marital_status(X,Y):-Y \=married, Y \=single, write('what is your marital status: married or single?'), read(Y), nl, asserta(marital_status(X,Y)).
%ask_marital_status(X,Y):-Y \= married; Y \= single, ask_marital_status(X,Y).
ask_income(X,Y):-income(X,Y).
ask_income(X,Y):-not(income(X,Y)),write('what is your annual income?'), nl, read(Y), asserta(income(X,Y)).
ask_mortgage(X,Z):-mortgage(X,Z).
ask_mortgage(X,Z):-not(mortgage(X,Z)), write('what is your mortgage?'), read(Z), nl, asserta(mortgage(X,Z)).
ask_age(X,A):-age(X,A).
ask_age(X,A):-not(age(X,A)), write('what is your age?'), read(A), nl, asserta(age(X,A)).
moderate_risk(X):-ask_marital_status(X,Y), Y=married, ask_income(X,I), I=<50000, ask_mortgage(X,Z), Z=<50000,!.
moderate_risk(X):-ask_marital_status(X,M), M=married, ask_income(X,I), I=<50000,!.
moderate_risk(X):-ask_marital_status(X,M), M=single, ask_income(X,I), I=<35000,!.
stable_risk(X):-ask_marital_status(X,M), M=married, ask_income(X,I), I=<50000, ask_mortgage(X,Z), Z>50000,!.
stable_risk(X):-ask_marital_status(X,M), M=single, ask_income(X,I), I>35000, ask_age(X,A), A>50, !.
high_risk(X):-ask_marital_status(X,M), M=single, ask_income(X,I), I>35000, ask_age(X,A), A=<50, !.
invest(X,oil):-stable_risk(X),!.
invest(X,telecommunications):-moderate_risk(X),!.
invest(X,computers):-high_risk(X),!.
第三个 "ask_martial_status" 是我目前试图让用户重新输入他们的决定,但它不起作用。我已经尝试使用 Prolog 的 AND 运算符 (,) 和它们的 or 运算符 (;) - 两者都没有区别(对于我放在 Y\= married 和 Y\=single 之间的内容)。当我输入错误的输入时,我只得到 "false" 返回。下面是一个例子:
?- main(X,Z).
what is your name?logan.
what is your marital status: married or single?|: widowed.
false.
注释掉的行(带有 %)是之前尝试让程序运行但也失败了。当我 Google 解决这个问题时,我很惊讶我无法找到一个快速的 YouTube 视频/文章来阅读。有人可以帮我吗?
您可以通过这种方式解决您的问题(相关预聚焦的片段):
ask_marital_status(X,Y):-
\+ marital_status(X,Y),
write('what is your marital status: married or single?'),
read(Y1),
( (Y1 == single ; Y1 == married) ->
Y = Y1,
asserta(marital_status(X,Y));
ask_marital_status(X,Y)
).
你可以用(Y1 = single ; Y1 = married)
检查你读取的值(Y1
)是single
还是married
(;
表示或)。然后,如果是 (->
),则继续进行谓词的其余部分。否则,(在 asserta/1
旁边的 ;
之后)你调用 recursively marital_status/2
.
编辑:感谢 Paulo Moura 的评论,=/2
(统一)必须替换为 ==/2
(平等),以使代码按预期运行。
读取和验证用户输入的传统方法是使用以下模板:
ask(Data) :-
repeat,
write(Prompt),
read(Data),
valid(Data),
!.
将此模板应用于您的案例,我们可以编写:
ask_marital_status(Status) :-
repeat,
write('What is your marital status (married or single)?'),
read(Status)
( Status == married
; Status == single
),
!.
作为一般规则,最佳做法是将询问用户输入与处理输入(在您的情况下断言事实)分开。
高级解决方案将使用消息打印和问题询问机制进行用户交互(参见 https://logtalk.org/2019/11/14/abstracting-user-interaction.html)。但这是一个更高级的话题。
我是 Prolog 的新手,正在尝试实现教科书中的示例。我已经能够让示例正常工作(通过以前的 Stack Overflow 帖子的明确帮助!),但现在它要求我验证用户输入:"Modify the given decision tree program, so that when the user responds to a question with an illegal answer, the system will ask him/her to reenter an answer which is among the specified choices."
在下面的程序中,对于婚姻状况,决策树中考虑的指定唯一选项是 "single" 或 "married." 如果您输入任何其他内容,目标是让您重新输入您的决定。
这对我不起作用。我的代码如下:
:-dynamic income/2.
:-dynamic marital_status/2.
:-dynamic mortgage/2.
:-dynamic age/2.
marital_status(joe,married).
income(joe,60000).
mortgage(joe,20000).
age(joe,45).
main(X,Z):-var(X), write('what is your name?'),read(X), invest(X,Z),!.
main(X,Z):-invest(X,Z),!.
ask_marital_status(X,Y):-marital_status(X,Y).
ask_marital_status(X,Y):-not(marital_status(X,Y)), write('what is your marital status: married or single?'), read(Y), nl, asserta(marital_status(X,Y)).
ask_marital_status(X,Y):-Y \=married, Y \=single, write('what is your marital status: married or single?'), read(Y), nl, asserta(marital_status(X,Y)).
%ask_marital_status(X,Y):-Y \= married; Y \= single, ask_marital_status(X,Y).
ask_income(X,Y):-income(X,Y).
ask_income(X,Y):-not(income(X,Y)),write('what is your annual income?'), nl, read(Y), asserta(income(X,Y)).
ask_mortgage(X,Z):-mortgage(X,Z).
ask_mortgage(X,Z):-not(mortgage(X,Z)), write('what is your mortgage?'), read(Z), nl, asserta(mortgage(X,Z)).
ask_age(X,A):-age(X,A).
ask_age(X,A):-not(age(X,A)), write('what is your age?'), read(A), nl, asserta(age(X,A)).
moderate_risk(X):-ask_marital_status(X,Y), Y=married, ask_income(X,I), I=<50000, ask_mortgage(X,Z), Z=<50000,!.
moderate_risk(X):-ask_marital_status(X,M), M=married, ask_income(X,I), I=<50000,!.
moderate_risk(X):-ask_marital_status(X,M), M=single, ask_income(X,I), I=<35000,!.
stable_risk(X):-ask_marital_status(X,M), M=married, ask_income(X,I), I=<50000, ask_mortgage(X,Z), Z>50000,!.
stable_risk(X):-ask_marital_status(X,M), M=single, ask_income(X,I), I>35000, ask_age(X,A), A>50, !.
high_risk(X):-ask_marital_status(X,M), M=single, ask_income(X,I), I>35000, ask_age(X,A), A=<50, !.
invest(X,oil):-stable_risk(X),!.
invest(X,telecommunications):-moderate_risk(X),!.
invest(X,computers):-high_risk(X),!.
第三个 "ask_martial_status" 是我目前试图让用户重新输入他们的决定,但它不起作用。我已经尝试使用 Prolog 的 AND 运算符 (,) 和它们的 or 运算符 (;) - 两者都没有区别(对于我放在 Y\= married 和 Y\=single 之间的内容)。当我输入错误的输入时,我只得到 "false" 返回。下面是一个例子:
?- main(X,Z).
what is your name?logan.
what is your marital status: married or single?|: widowed.
false.
注释掉的行(带有 %)是之前尝试让程序运行但也失败了。当我 Google 解决这个问题时,我很惊讶我无法找到一个快速的 YouTube 视频/文章来阅读。有人可以帮我吗?
您可以通过这种方式解决您的问题(相关预聚焦的片段):
ask_marital_status(X,Y):-
\+ marital_status(X,Y),
write('what is your marital status: married or single?'),
read(Y1),
( (Y1 == single ; Y1 == married) ->
Y = Y1,
asserta(marital_status(X,Y));
ask_marital_status(X,Y)
).
你可以用(Y1 = single ; Y1 = married)
检查你读取的值(Y1
)是single
还是married
(;
表示或)。然后,如果是 (->
),则继续进行谓词的其余部分。否则,(在 asserta/1
旁边的 ;
之后)你调用 recursively marital_status/2
.
编辑:感谢 Paulo Moura 的评论,=/2
(统一)必须替换为 ==/2
(平等),以使代码按预期运行。
读取和验证用户输入的传统方法是使用以下模板:
ask(Data) :-
repeat,
write(Prompt),
read(Data),
valid(Data),
!.
将此模板应用于您的案例,我们可以编写:
ask_marital_status(Status) :-
repeat,
write('What is your marital status (married or single)?'),
read(Status)
( Status == married
; Status == single
),
!.
作为一般规则,最佳做法是将询问用户输入与处理输入(在您的情况下断言事实)分开。
高级解决方案将使用消息打印和问题询问机制进行用户交互(参见 https://logtalk.org/2019/11/14/abstracting-user-interaction.html)。但这是一个更高级的话题。