Find items from a list in another prolog

0

Good I am working in a drug recommender in which I have a list of medicines and another with allergies, a fact contains (medicine, component) where X medicine contains Y component and another that is has_allergy (patient, component_allergic) where X is allergic to Y component. What I want is to get the list of medicines that do not contain that medicine but I can not get it. Example:

Tiene_alergia(Pepe, amoxicilina).
Tiene_alergia(pepe, ampicilina).

Contiene(clamoxil, amoxicilina).
Contiene(britapen, ampicilina).

Now by findall I get 2 lists A = list of patient allergies and L = list of drug components.

I call the rule to delete (A, L, L2). L2 will be the list after filtering.

Eliminar([],[]).
Eliminar(X, [Y|Ys], L2) :- posicion(X, [Y|Ys],Pos), borrar(Pos, [Y|Ys], L2).
Eliminar([X|Xs], [Y|Ys], L2):- eliminar(X, [Y|Ys]) ; eliminar(Xs, Ys).

Posicion(E, [E, _], 0).
Posicion(E,[_|C], P):- posición (E,C,P1), P is P1+1.

Borrar(I, L, L2) :- insertar(_,I,L2,L).
Insertar(X, 0, L2, [X|L2]).
Insertar(X, Pos, [C|R], [C|R2]) :- Pos1 is Pos -1, insertar(X, pos1, R, R2).

The thing is that if I call

 eliminar([amoxicilina,ampicilina],[amoxicilina, ampicilina], L2).

L2 = [ampicilina]; and this is wrong it should be []

Would there be a way to fix it?

Thanks in advance.

    
asked by john ibarra 25.02.2018 в 14:06
source

1 answer

0

If I did not misunderstand, the delete / 2 predicate removes each item from list A of the list L. For this you can use the predicate subtract / 3 with the form:

subtract(L, A, L2).

For example:

?- subtract([amoxicilina,ampicilina],[amoxicilina, ampicilina], L2).
L2 = [].

?- subtract([amoxicilina,ampicilina,componenteAux1, componenteAux2], 
[amoxicilina, ampicilina], L2).
L2 = [componenteAux1, componenteAux2].

Now, I think that the representation you are using for the facts can be a little better, for example, if you consider representing the fact contains / 2 in the following way:

contiene(medicamento,[lista de componentes de medicamento]).

It would be a little clearer and more direct to work on that fact.

However, and taking into account the definition of your facts, you can define the following predicates:

alergias(Paciente, Alergias):-
 findall(ComponenteAlergico, tiene_alergia(Paciente, ComponenteAlergico), 
 Alergias).

medicamentos(Paciente, MedicamentosAptos):-
 findall(Medicamento,contiene(Medicamento, _), ListaMedicamentos), 
 list_to_set(ListaMedicamentos, Medicamentos),
 getMedicamentosComponentes(Medicamentos, MedicamentosComponentes),
 alergias(Paciente, Alergias),
 getMedicamentosAptos(Alergias, MedicamentosComponentes, 
 MedicamentosAptos).


getMedicamentosComponentes([],[]).
getMedicamentosComponentes([H|B],[[H,Componentes]|R]):-
 findall(Componente, contiene(H, Componente), Componentes),
 getMedicamentosComponentes(B,R).


getMedicamentosAptos(_,[],[]).
getMedicamentosAptos(Alergias, [[Medicamento,Componentes]|Medicamentos], 
[Medicamento|R]):-
 subtract(Componentes, Alergias, Resultado),
 Resultado = Componentes,
 getMedicamentosAptos(Alergias, Medicamentos, R).

getMedicamentosAptos(Alergias, [[Medicamento,Componentes]|Medicamentos], 
R):-
 getMedicamentosAptos(Alergias, Medicamentos, R).

The predicate getMedicamentsComponents / 2 arms the list [[medicine, [components]], [medicine, [components]], ...]. The predicate getMedicamentosAptos / 3 takes as input a list of allergies, the medication list of the predicate getMedicamentosComponentes / 2 and returns a list of medicines whose components does not contain any component of the list of allergies. Finally, the drug / 2 predicate takes a Patient patient as input and returns a list of MedicationsAptics of drugs suitable for that patient.

    
answered by 28.03.2018 в 22:21