我需要根据某些用户的答案求和一个变量,并且我开始了解Prolog语法和范例。
现在,我可以读取用户数据并进行打印,但是我无法累积结果,因为现在结果不一致。
我现在拥有的是:
inicio :-
write('¿You have overweight yes/no?'),
read(R1),
write('¿Are you a smoker yes/no?'),
read(R2),
write('¿Do you have some direct relative with diabetes?'),
read(R3),
Risk is 0,
( R1 = yes -> Risk is Risk + 2 ; Risk is Risk + 0 ),
imprimir(['The result is ', Risk]),
( R2 = yes -> Risk is Risk + 1 ; Risk is Risk + 0 ),
imprimir(['The result is ', Risk]),
( R3 = yes -> Risk is Risk + 3 ; Risk is Risk + 0 ),
imprimir(['The result is ', Risk]).
imprimir([]).
imprimir([Term| Terms]) :-
write(Term),
imprimir(Terms).
答案 0 :(得分:1)
我将向您展示一种基本不同的方法来实施该程序,并更好地利用Prolog。首先,让我们建立一个惩罚表。为程序的配置创建表通常是一件有用的事情:
risk_penalty(overweight, 2).
risk_penalty(smoker, 1).
risk_penalty(diabetes, 3).
现在,我们已经采用统一的方式来思考问题,让我们看看是否可以采用统一的方式来从用户那里获取信息。让我们使用动态存储来跟踪用户告诉我们的内容,因为它将简化以后的查询:
:- dynamic risk/2.
ask(Prompt, Fact) :-
format('~a [yes/no]> ', [Prompt]),
read(Response),
assertz(risk(Fact, Response)).
现在,我们有了一些谓词可以用来采访用户。这种打印-读取-断言功能在像您这样的小型专家系统中非常常见,因为它可以帮助您将系统的逻辑与前端分开。当您执行ask('Do you have X?', has_x)
时,动态存储将收到risk(has_x, yes)
或risk(has_x, no)
,具体取决于用户输入的内容。通过检查并重新询问是否有奇怪的内容,它还为您提供了使用户输入更可靠的自然位置。
现在,我们可以更清晰地完成您的初始循环了:
inicio :-
ask('Are you overweight?', overweight),
ask('Are you a smoker?', smoker),
ask('Do you have some direct relative with diabetes?', diabetes).
这只是采访部分。现在,如果您运行了一次,说回答“是”,“否”,“是”,则数据库将包含以下事实:
?- risk(Factor, Response).
Factor = overweight,
Response = yes ;
Factor = smoker,
Response = no ;
Factor = diabetes,
Response = yes.
我们现在要做的是选择“是”因素,然后查找它们的惩罚并将其加起来。为此,我们可以使用findall/3
,它使用一个模板,一个目标并返回结果列表:
?- findall(risk(Factor, Response), risk(Factor, Response), Responses).
Responses = [risk(overweight, yes), risk(smoker, no), risk(diabetes, yes)].
如您所见,我在这里使用了相同的模板和目标,只是为了查看所有结果,但是我们可以输入“是”以将其过滤为仅关注我们所关注的风险因素:
?- findall(risk(Factor), risk(Factor, yes), Responses).
Responses = [risk(overweight), risk(diabetes)].
现在,您可以看到Template(第一个参数)只是一些任意结构,其中填充了findall/3
通过运行第二个参数Goal
找到的变量。因此,如果我们在目标查询中查找惩罚值的列表,我们也可以只获取它们。像这样:
?- findall(Penalty, %% <- template
(risk(Factor, yes), risk_penalty(Factor, Penalty)), %% <- goal
Penalties). %% <- result
Penalties = [2, 3].
然后我们可以仅添加sumlist/2
来添加所有内容:
?- findall(Penalty,
(risk(Factor, yes), risk_penalty(Factor, Penalty)),
Penalties),
sumlist(Responsa, Score).
Responsa = [2, 3],
Score = 5.
现在我们可以完成inicio/0
谓词:
inicio :-
retractall(risk(_, _)),
ask('Are you overweight?', overweight),
ask('Are you a smoker?', smoker),
ask('Do you have some direct relative with diabetes?', diabetes)
findall(Penalty,
(risk(Factor, yes), risk_penalty(Factor, Penalty)), Penalties),
sumlist(Penalties, Score),
format('The result is ~a~n', [Score]).
现在运行时如下所示:
?- inicio.
Are you overweight? [yes/no]> yes.
Are you a smoker? [yes/no]> |: no.
Do you have some direct relative with diabetes? [yes/no]> |: yes.
The result is 5
true.
我希望您能看到令人愉悦的结果,减少程序性,并易于修改和维护。