I can't understand the result of my code in Pr

2019-08-04 09:43发布

问题:

I am doing Prolog Programming for my research and I got some problems.. First, all of my codes are below.

%% 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).

As you can see, I want to make a bar_graph from 10 input lines by extracting symptoms.. But when I executed this code, I got the result as below...

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 

I only typed one symptom (runny_nose). I want to get Score for "cold" is 0, Score for "severe_cold" is 50 and BarGraph result... But What Happened? I can't find..

*****Edited****** I found that the problem is related to local variables (Line1, .. ,Line10) But how can I deal with? If I can make all the variables; Line1, ... , Line10 as global variables then, I think the problem can be solved...

****Addition*****

I changed my 'start' predicate as follows...I didn't use 'diagnosis' and 'hypothesis' predicates/ But the problems is maybe.. 'get_symptoms' predicate. Is there any choice I can choose except that I don't use 'get_symptoms' and 'symptoms' predicates...? Then the code will become very coarse...

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:

When programming in Prolog, you need to do some research into the language to understand how it works. Many Prolog beginners make the mistake of learning a couple of snippets of Prolog logic and then apply what they know of other languages to attempt to create a valid Prolog programming. However, Prolog doesn't work like other common languages at all.

Regarding variables, there are no globals. Variables are always "local" to a predicate clause. A predicate clause is one of one or more clauses that describe a predicate. For example:

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).

These are three clauses describing the predicate foo/2. The value of X or Y instantiated in one clause isn't visible to the other clauses.

If you want to instantiate a variable in one predicate and use it in another, you have to pass it as a parameter:

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

Here, foo might instantiate L using some logic and based upon the instantiated value of [1,2,3,4] for the first argument. Then L (now instantiated) is passed as the first argument to the predicate bar.

If you need a value to be persistent as data, you could assert it as a fact as follows:

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).

This would work, but is not a desirable approach in Prolog to "fake" global variables. Asserting items into persistent data is designed for the purpose of maintaining a Prolog database of information.

So you can see that the logic you have involving Line1, Line2, ... will not work. One clue would be that you must have received many warnings about these variables being "singleton". You need to study Prolog a bit more, then recast your logic using that knowledge.



标签: prolog