我无法理解Prolog编程中的代码结果

时间:2013-12-11 11:12:15

标签: prolog

我正在为我的研究做Prolog编程,但我遇到了一些问题.. 首先,我的所有代码都在下面。

%% Lines are without period(.)

diagnosis :-
    readln(Line1),
    readln(Line2),
    readln(Line3),
    readln(Line4),
    readln(Line5),
    readln(Line6),
    readln(Line7),
    readln(Line8),
    readln(Line9),
    readln(Line10),
    write(Line1),nl,
    write(Line2),nl,
    write(Line3),nl,
    write(Line4),nl,
    write(Line5),nl,
    write(Line6),nl,
    write(Line7),nl,
    write(Line8),nl,
    write(Line9),nl,
    write(Line10),nl.
    %% (get_symptom(Line1,[man]) -> write('man!!!!!!!!!')),
    %% (get_symptom(Line2,[woman]) -> write('woman!!!!!!!!!')).
    %% if A then B else C, (A->B; C)

%% grammar
s --> np, vp.
np --> det, n.
vp --> v, np.
det --> [a].
n --> [man].
v --> [has].
n --> [woman].
n --> [fever].
n --> [runny_nose].

get_symptom(Line,N) :- s(Line,[]), member(N,Line).

member(X, [X|T]).
member(X,[H|T]) :-
    member(X,T).

%% FindSymptom(Line, [Symptom]) : - s(Line,[]), np(_, _, object,[a,
%% Symptom]), n(singular, [Symptom], []).

start :-
    write('What is the patient''s name? '),
        readln(Patient), %% Here, this can be used for input of all symtoms
    diagnosis,


    hypothesis(Patient,cold,S1),
    append([cold/S1/red],[],N1),  write(S1),

    write('until...'),

    hypothesis(Patient,severe_cold,S2), write(S2),
    append([severe_cold/S2/red],N1,BarList),

    write('until...'),


        %% write(Patient,"probably has ",Disease,"."),nl.
    hypothesis(Patient,Disease,100),
    write(Patient),
    write(' probably has '),
    write(Disease),
    write('.'),

    test_barchart(BarList).
start :-
    write('Sorry, I don''t seem to be able to'),nl,
        write('diagnose the disease.'),nl.

symptom(Patient,fever) :-
    get_symptom(Line1, [fever]);
    get_symptom(Line2, [fever]);
    get_symptom(Line3, [fever]);
    get_symptom(Line4, [fever]);
    get_symptom(Line5, [fever]);
    get_symptom(Line6, [fever]);
    get_symptom(Line7, [fever]);
    get_symptom(Line8, [fever]);
    get_symptom(Line9, [fever]);
    get_symptom(Line10, [fever]).

symptom(Patient,runny_nose) :-
    get_symptom(Line1, [runny_nose]);
    get_symptom(Line2, [runny_nose]);
    get_symptom(Line3, [runny_nose]);
    get_symptom(Line4, [runny_nose]);
    get_symptom(Line5, [runny_nose]);
    get_symptom(Line6, [runny_nose]);
    get_symptom(Line7, [runny_nose]);
    get_symptom(Line8, [runny_nose]);
    get_symptom(Line9, [runny_nose]);
    get_symptom(Line10, [runny_nose]).

hypothesis(Patient,cold,Score_Cold) :-
    (symptom(Patient,fever), Score_Cold is 100),write('!!!');
    Score_Cold is 0.

hypothesis(Patient,severe_cold,Score_Severe) :-
    ((symptom(Patient,fever), Score1 is 50);
    Score1 is 0),
    ((symptom(Patient, runny_nose), Score2 is 50);
    Score2 is 0),
    Score_Severe is Score1 + Score2.

%% hypothesis(Disease) :-
    %%(hypothesis1(Patient,cold,Score1),
    %%Score1 =:= 100 -> Disease = cold);
    %%(hypothesis2(Patient,severe_cold,Score2),
    %%Score2 =:= 100 -> Disease = severe_cold).

%% make graph for the result
:- use_module(library(pce)).
:- use_module(library(plot/barchart)).
:- use_module(library(autowin)).

test_barchart(BarList):-
    new(W, picture),
    send(W, display, new(BC, bar_chart(vertical,0,100))),
    forall(member(Name/Height/Color,
              BarList),
           (   new(B, bar(Name, Height)),
               send(B, colour(Color)),
               send(BC, append, B)
           )),
    send(W, open).
%% [X/100/red, y/150/green, z/80/blue, v/50/yellow]

%% append List
append([], L, L).
append([H|T], L2, [H|L3]):-
    append(T, L2, L3).

如您所见,我想通过提取症状从10个输入行创建一个bar_graph。 但是当我执行这段代码时,我得到的结果如下......

1 ?- start.
What is the patient's name? GJ
|: a man has a runny_nose
|: a
|: a
|: a
|: a
|: a
|: a
|: a
|: a
|: a
[a,man,has,a,runny_nose]
[a]
[a]
[a]
[a]
[a]
[a]
[a]
[a]
[a]
!!!100until...100until...!!![GJ] probably has cold.
true 

enter image description here

我只输入了一个症状(runny_nose)。我希望得分“冷”是0,得分为“severe_cold”是50和BarGraph结果......但是发生了什么?我找不到..

*****编辑****** 我发现问题与局部变量(Line1,..,Line10)有关但是我该如何处理呢?如果我能做出所有的变数;然后,Line1,...,Line10作为全局变量,我认为问题可以解决......

**** *****加成

我改变了我的'开始'谓词如下......我没有使用'诊断'和'假设'谓词/但问题可能是......'get_symptoms'谓词。有什么选择我可以选择,除了我不使用'get_symptoms'和'症状'谓词......?然后代码将变得非常粗糙......

start :-
    write('What is the patient''s name? '),
    readln(Patient), %% Here, this can be used for input of all symtom

    readln(Line1),
    readln(Line2),
    readln(Line3),
    readln(Line4),
    readln(Line5),
    readln(Line6),
    readln(Line7),
    readln(Line8),
    readln(Line9),
    readln(Line10),

    (symptom(Patient,fever,Line1,Line2,Line3,Line4,Line5,Line6,Line7,Line8,Line9,Line10) -> (Cold is 80, Severe_Cold is 50)),

    (symptom(Patient,runny_nose,Line1,Line2,Line3,Line4,Line5,Line6,Line7,Line8,Line9,Line10) -> Severe_Cold is Severe_Cold + 50),
    write(Severe_Cold), write(Cold),

    append([cold/Cold/red],[],N1),

    append([severe_cold/Severe_Cold/red],N1,BarList),


    %% write(Patient,"probably has ",Disease,"."),nl.
    write(Severe_Cold),
    ((Cold =:= 100 -> Disease = cold) ; (Severe_Cold =:= 100 -> Disease = severe_cold)),
    write(Patient),
    write(' probably has '),
    write(Disease),
    write('.'),

    test_barchart(BarList).

1 个答案:

答案 0 :(得分:3)

在Prolog中编程时,您需要对语言进行一些研究,以了解它的工作原理。许多Prolog初学者错误地学习了几段Prolog逻辑片段,然后应用他们所知的其他语言来尝试创建有效的Prolog编程。但是,Prolog根本不像其他常用语言那样工作。

关于变量,没有全局变量。变量始终是谓词子句的“本地”。谓词子句是描述谓词的一个或多个子句之一。例如:

foo(X, Y) :- (some logic including X and Y).
foo(X, Y) :- (some other logic including X and Y).
foo(X, X) :- (some other logic including X).

这三个子句描述了谓词foo/2。在一个子句中实例化的XY的值对其他子句不可见。

如果要在一个谓词中实例化变量并在另一个谓词中使用它,则必须将其作为参数传递:

foo([1,2,3,4], L),
bar(L, X).

这里,foo可以使用某些逻辑并基于第一个参数的L的实例化值来实例化[1,2,3,4]。然后L(现在实例化)作为谓词bar的第一个参数传递。

如果您需要一个值作为数据持久化,您可以将其断言为如下事实:

foo :-
    (some logic that determines X),
    assertz(my_fact(X)),
    (more logic).

bar :-
    my_fact(X),    % Will instantiate X with what was asserted
    (some logic using X).

这可行,但在Prolog中不是一种理想的“假”全局变量。将项目断言为持久数据旨在维护Prolog数据库信息。

因此,您可以看到涉及Line1Line2,......的逻辑不起作用。一个线索是,您必须收到许多关于这些变量为“单身”的警告。您需要更多地学习Prolog,然后使用该知识重新构建您的逻辑。