Prolog Recursion skipping same results

前端 未结 3 974
余生分开走
余生分开走 2020-12-04 02:28

My code runs but the problem is it shows the same results more than once. Here\'s my code:

disease(hiv,[sore_throat,headache,fever,rash]).
disease(pregnancy         


        
3条回答
  •  臣服心动
    2020-12-04 02:57

    You have to remember what diseases you already collected when checking the symptoms. You need to collect (aggregate) the diseases in a list, and check whether a disease is already present in the list before adding it. You can then print the list at the end or print out each new disease as it is added to the list.

    I would implement it this way:

    diagnose(Name, Symptoms) :- diagnose0(Name, Symptoms, []).
    
    diagnose0(Name, [], Diseases) :-
        print_diseases(Name, Diseases).
    diagnose0(Name, [H|T], DIn) :-
        disease(Disease, Symptoms),
        member(H, Symptoms),
        % you may want to add a cut here to avoid choicepoints
        (
            member(Disease, DIn)
        ->
            diagnose0(Name, T, DIn)
        ;
            DOut = [Disease|DIn],
            diagnose0(Name, T, DOut)
        ).
    
    print_diseases(_Name, []).
    print_diseases(Name, [H|T]) :-
        write(Name), write(' has/is '), writeln(H),
        print_diseases(Name, T).
    

    The disease/2 facts are as in your code.

    This gives:

    ?- diagnose(kevin, [sore_throat, fatigue, tiredness, rash]).
    kevin has/is flu
    kevin has/is pregnancy
    kevin has/is hiv
    Yes (0.00s cpu, solution 1, maybe more)
    

    The next step then would obviously be to find a way to express that some diagnoses represent alternatives for a given symptom, and choose between these different alternatives. With the symptoms listed in the query, Kevin should have flu and HIV, but I doubt that pregnancy is a correct diagnosis for Kevin. This is related to the comment about a cut that I inserted in the second clause of diagnose/3: without the cut, you can get more than one solution, each representing a different set of diseases that match the set of symptoms. If you add a cut, you only get the first solution (including pregnancy). The second solution only contains flu and HIV.

    BTW, member/2 is a built-in predicate, so you don't need to define your own.

提交回复
热议问题