SWI-Prolog list result - prolog

I'm coding in prolog, but I have a issue. How can I make that the answer appears just once? for example I just want that "X = uni, X = uca, X = unam" but instead it just keep showing me the options repeatedly.
This is some of it:
is(uni, college).
is(uca, college).
is(unan, college).
is(computation, carrer).
In this part I'm assigning available places to the carrer
has(computation, available_places, 200).
and finally assigning the carrer to a college
offers(unan, computation).
offers(uni, computation).
offers(uca, computation).
and I make the query like this:
which(X):- is(X, college), is(Y, carrer), offers(X, Y),has(Y, available_places, Z), Z<300.
but the result as I said at the beggining, show me the names of the college repeadtedly. Any idea how to solve this? D:

Related

Prolog, Outputting a Variable After a Relation is Used

This is my first-day learning prolog and I would like to write a program that decides what shoes I should wear based on the weather and what kind of appointment I have at the office. The main "function" would be declared for example:
"go :- outfit(snow, 15, casual, F1), write(F1)."
Where snow is the weather, 15 is the temperature(not relevant now), and casual is the formality of the appointment. "write(F1)" will display the "output" so the variable F1 needs to be the result of said relation(s). Here are the rules for what shoes to wear:
%Rules for weather
rain(Weather) :- (Weather = 'rain').
snow(Weather) :- (Weather = 'snow').
nice(Weather) :- (Weather = 'nice').
clear(Weather) :- (Weather = 'clear').
%Rules for formality
formal(Appointment) :- (Appointment = 'formal').
semiformal(Appointment) :- (Appointment = 'semiformal').
casual(Appointment) :- (Appointment = 'casual').
%Rules for when to wear a type of footwear
dressShoes(Appointment) :- formal(Appointment).
boots(Appointment, Weather) :- not(formal(Appointment)), (rain(Weather);snow(Weather)).
sneakers(Appointment, Weather) :- not(formal(Appointment)), (nice(Weather);clear(Weather)).
This is where my issue is, I am not sure how to tie the last three relations to a single relation that fills the variable "F1" for my final "outfit" function. I am a C++ guy, so I would like to essentially place a string into F1 like "[sneakers]" or "[boots]" but this is part of my growing pains with prolog. Any help is much appreciated.
Some misunderstandings about Prolog I guess. This kind of rule:
rule(Variable) :- (Variable = 'value').
You don't need to quote 'value', it is already an atom. Whatever book you are reading, look up atoms. It becomes:
rule(Variable) :- (Variable = value).
You don't need the extra parentheses in the rule definition. It becomes:
rule(Variable) :- Variable = value.
You don't need the explicit unification in the body. There is nothing else happening between the head and the body. So you don't need a variable, either. It becomes:
rule(value).
Applying this to your program, I get:
rain(rain).
snow(snow).
nice(nice).
clear(clear).
%Rules for formality
formal(formal).
semiformal(semiformal).
casual(casual).
Those rules say pretty much nothing ;-)
Your example at the very top:
go :- outfit(snow, 15, casual, F1), write(F1).
Does exactly the same as just calling outfit(snow, 15, casual, F1). So what is the purpose of the "go" and the "write"? Skip them I guess.
The logic of your program: can you explain it without code? Your code is so unusual that I have to guess.
If you want to say, "If the appointment is formal, put on dress shoes", you could write it like this:
occasion_shoes(Occasion, Shoes) :-
formality_occasion(Formality, Occasion),
formality_shoes(Formality, Shoes).
formality_occasion(formal, evening_party).
formality_occasion(semi_formal, office).
formality_shoes(formal, dress_shoes).
Do you see what is going on? You match the occasion to the shoes. To do that, you look up the formality of the occasion in the table formality_occasion/2 and then match it to the formality of the shoes in the formality_shoes/2 table.
If you are struggling to model your problem, you can also read up on relational database design.

Sum up data from facts

(Given a list of movies, write a PROLOG rule to add and display the total takings.)
This is my question I am basically trying to add an integer value give a list of movies from the list below. I am quite new in Prolog and I don't really understand how things work.
takings(air_force_one,315000000).
takings(american_beauty,336000000).
takings(american_pie,201700000).
takings(american_wedding,230700000).
takings(armageddon,554600000).
takings(as_good_as_it_gets,313300000).
takings(austin_powers_in_goldmember,289000000).
takings(babe,249000000).
takings(back_to_the_future,350600000).
takings(back_to_the_future_part_ii,332000000).
takings(back_to_the_future_part_iii,243700000).
takings(robots,245600000).
takings(hulk,241700000).
takings(bad_boys_ii,261900000).
The Rule I have written so far works for only one movie.
Example:
?- score([robots],Y).
Y = 245600000.
?- score([robots,hulk],Y).
false.
?- score([robots,hulk,bad_boys__ii],Y).
false.
Rule written :
score([Movies], Money):-
findall(Profit,(takings(Movies, Profit)), ListOfProfit),
sum_list(ListOfProfit, Money).
Related question asking for a recursive answer.

Prolog compound statement returning multiple variables

I'm super new to Prolog, like, my professor assigned us a program and just asked us to watch a couple youtube videos. No lecture.
So anyway, here's the issue:
I'm supposed to create a pharmacist software that looks up drug interactions.
When I enter a specific drug, then Drug-variable, and Interaction-variable, I get the first drug and interaction in the list (of like, 100 drugs that interact with temazepam):
?- interacts(temazepam,Drug,Interaction).
Drug = thalidomide,
Interaction = neutropenia .
Part 1) How can I get every drug and its interaction from, say, temazepam?
Partial program listed below [because I have 1609 lines of drug interactions listed]:
interacts(X,Y,Interaction):-
Drug(X),
Drug(Y),
Interaction.
Interaction:-
Drug(X),
Drug(Y).
interacts(gatifloxacin,zolpidem,attempted_suicide).
interacts(gatifloxacin,zolpidem,insomnia).
interacts(gatifloxacin,warfarin,cardiac_decompensation).
interacts(gatifloxacin,isosorbide-5-mononitrate,arteriosclerotic_heart_disease).
interacts(gatifloxacin,rosiglitazone,hyperglycaemia).
interacts(gatifloxacin,bortezomib,hyperglycaemia).
interacts(gatifloxacin,mometasone,asthma).
interacts(gatifloxacin,cisplatin,hyperglycaemia).
interacts(gatifloxacin,cisplatin,bone_marrow_failure).
interacts(gatifloxacin,montelukast,difficulty_breathing).
interacts(temazepam,thalidomide,neutropenia).
interacts(temazepam,thalidomide,thrombocytopenia).
interacts(temazepam,timolol,drowsiness).
interacts(temazepam,tizanidine,acid_reflux).
interacts(temazepam,tizanidine,heart_attack).
interacts(temazepam,tolterodine,amnesia).
Part 2) I need to be able to list an interaction and get back every drug that caused it.
I guess just the side-effect then all drug interactions listed would be better than listing drug1+sideEffect = drug2.
Example:
?- interacts(Drug,Drug,amnesia).
Part 3) I should be able to enter a single drug, and get everything with interactions and everything with no interactions.
Example:
?- interacts(valacyclovir,Drug,Interaction).
Drug = zolpidem,
Interaction = anxiety
But for everything
Excuse me for the edits!
Thanks so much in advance!
You can use the built-in predicate findall/3 for that:
drug_allinteractions(Drug,AI) :-
findall((D,I),interacts(Drug,D,I),AI).
The only goal of drug_allinteractions/2 is using findall/3 to query interacts/3 and put its second and third argument into the list AI as a tuple (D,I). Example query: Wich interacting drugs with what interaction-effect are known for gatifloxacin?:
?- drug_allinteractions(gatifloxacin,L).
L = [(zolpidem,attempted_suicide),(zolpidem,insomnia),(warfarin,cardiac_decompensation),(isosorbide-5-mononitrate,arteriosclerotic_heart_disease),(rosiglitazone,hyperglycaemia),(bortezomib,hyperglycaemia),(mometasone,asthma),(cisplatin,hyperglycaemia),(cisplatin,bone_marrow_failure),(montelukast,difficulty_breathing)]
Alternatively, if you just want to query interacts/3 and not write a program:
?- findall((D,I),interacts(gatifloxacin,D,I),AI).
AI = [(zolpidem,attempted_suicide),(zolpidem,insomnia),(warfarin,cardiac_decompensation),(isosorbide-5-mononitrate,arteriosclerotic_heart_disease),(rosiglitazone,hyperglycaemia),(bortezomib,hyperglycaemia),(mometasone,asthma),(cisplatin,hyperglycaemia),(cisplatin,bone_marrow_failure),(montelukast,difficulty_breathing)]
As for your added part 2): You can use findall on your original query:
?- findall((D1,D2),interacts(D1,D2,amnesia),AI).
AI = [(temazepam,tolterodine)]
Note, that unlike in your example I wrote two different variables D1 and D2 for the drugs, otherwise you are asking which drug has the interaction-effect amnesia with itself.
Considering your added part 3) I'm not entirely sure what you want. Your query reads: "Show me all drugs that interact with valacyclovir plus the associated effect". That is basically the same as your very first query, just for a different drug. You can query for all drugs in the relation interacts/3 interactively without showing the interacting drugs and the effects by:
?- interacts(D,_,_).
D = gatifloxacin ? ;
...
Or query for an entire list without duplicates by using setof/3:
?- setof(D1,D2^I^interacts(D1,D2,I),AI).
AI = [gatifloxacin,temazepam]
If you, however, try to find a list of drugs that are not interacting with a given drug, you can write a predicate, say drug_noninteractingdrug/2...
:- use_module(library(lists)).
drug_noninteractingdrug(D,NID) :-
dif(D,NID), % D and NID are different
setof(D2,D^interacts(D,D2,_),L), % L ... all drugs interacting with D
interacts(NID,_,_), % NID ... drug...
\+member(NID,L). % ... that is not in L
... and query this using setof/3:
?- setof(NID,drug_noninteractingdrug(gatifloxacin,NID),NIDs).
NIDs = [temazepam]
With your given minimal example this query of course only yields one drug. Note that you need to include library(lists) for the predicate member/2.

Prolog error in loop

I would need help about Prolog.
I posted my code, the problem is that i do not obtain the expected result.
I want planning actions for moving on table all blocks until is possible. To do this I prompt :
?- do(while(some(x, block(x) & -onTable(x)),pi(x,putOnTable(x))),s0,S).
I expect to see a response like :
S = do(putOnTable(e), do(putOnTable(b), do(putOnTable(c), s0)))
but Prolog returns "false" only. Someone can help me??
% Golog interpreter
%:- [golog_swi].
:- discontiguous clear/2, on/3, onTable/2.
:- op(800,xfy,[&]).
do(E,S,do(E,S)):- primitive_action(E),poss(a,S).
% Primitive Action Declarations.
primitive_action(putOn(_,_)).
primitive_action(putOnTable(_)).
poss(putOn(X,Y),S) :- clear(X,S), clear(Y,S), \+ on(X,Y,S), \+ X=Y.
poss(putOnTable(X),S):- clear(X,S), \+(onTable(X,S)).
% Successor State Axioms.
on(X,Y,do(A,S)):- A = putOn(X,Y); on(X,Y,S), \+ (A = putOnTable(X); A = putOn(X,_)).
onTable(X,do(A,S)) :- A = putOnTable(X); onTable(X,S), \+ A= putOn(X,_).
clear(X,do(A,S)) :- on(Y,X,S), (A = putOn(Y,_) ; A = putOnTable(Y)); clear(X,S), \+ A = putOn(_,X).
% Restore suppressed situation arguments
restoreSitArg(onTable(X),S,onTable(X,S)).
restoreSitArg(on(X,Y),S,on(X,Y,S)).
restoreSitArg(clear(X),S,clear(X,S)).
block(X):- member(X,[a,b,c,d,e]).
% iniTial COndition
onTable(a,s0).
on(b,a,s0).
on(c,b,s0).
clear(c,s0).
onTable(d,s0).
on(e,d,s0).
clear(3,s0).
thank you!!!
Your predicate do/3 cannot succeed because the goal primitive_action/1 will fail with your query.
Currently, while/2 is not described in primitive_action/1 and it seems it is missing also from your program. So you need to extend primitive_action/1 by further facts, or add a new rule to do/3. And in addition to that you need to describe what while/2 means.
This question is actually about Golog. Your mistake is pretty mundane: you didn't copy the Golog interpreter code into your source file/directory.
Golog defines a number of high-level programming constructs, including while-loops and non-deterministic picks (pi), used here. I'm sure you don't want to reinvent Golog, so just go and get it. I'm assuming that your question is part of an assignment of sorts, and your teacher probably pointed you to the Golog interpreter. Otherwise, you can always find it on the pages of the cognitive robotics group at the Univ. of Toronto: http://www.cs.toronto.edu/cogrobo/main/systems/index.html

Am I using Pluralizer wrong?

Paging Jay Querido...
Downloaded the Pluralizer NuGet package. My goal is to display a string like so:
X contracts with Y partners in Z countries
If X is 1, word should change to contract. If Z is 1, word should change to country. Same for 1 partner.
The following does not work. It always results in TotalContracts being the same number for the whole sentence.
#Html.Pluralize("{_} {contract} with {_} {partner} in {_} {country}",
Model.TotalContracts, Model.TotalPartners, Model.TotalCountries)
#* result is X contracts with X partners in X countries *#
The following does work, but is not quite as readable. Is there a better way?
#Html.Pluralize("{_} {contract}", Model.TotalContracts) with
#Html.Pluralize("{_} {partner}", Model.TotalPartners.Count) in
#Html.Pluralize("{_} {country}", Model.TotalCountries)
It looks like my comment obscured an underscore. This works with a single call to Pluralize:
#Html.Pluralize("{0|_} {0|contract} with {1|_} {1|partner} in {2|_} {country}",
Model.TotalContracts, Model.TotalPartners, Model.TotalCountries)

Resources