I have noticed that if i use xpath(DOM, //table(N), T), the system extracts only the external tables, but if i have a table into another table, i can see it only i use findall/3. The predicate findall/3 extract all table, but i can't access to internal table. Why?
I use
xpath(DOM, //table(N), T)
to extract the N-th table, but the system extracts only external table. If i have for example:
<table>
<table>
</table>
<table>
i can't use xpath(DOM, //table(N), T), because i would have only one table. If I insert //table(2), the system fails. Instead, if i use findall/3 i have all table in the DOM, but with findall i haven't access to the n-th table. How can i do?
indexing works 'on levels', to access nested elements you can specify the path, or - if the path is only partially known - use multiple xpath calls.
test data (way too simple)
?- D=element(table,[id=one],[element(table,[id=two],[])]).
raw search operator indexed:
?- xpath($D, //table(N), T).
N = last,
T = element(table, [id=one], [element(table, [id=two], [])]) ;
N = last,
T = element(table, [id=two], []) ;
false.
fully known path
?- xpath($D, //table/table(#id), ID).
ID = two ;
false.
multiple xpath 'joined' (this is most flexible, but the behaviour of search operators need some apprenticeship...)
?- xpath($D, //table, T), xpath(T, table(#id), ID).
T = element(table, [id=one], [element(table, [id=two], [])]),
ID = two ;
false.
Related
I'm trying to implement a predicate in prolog where given any sample table with data, the contents of the table indices [+I, +J] should be printed on the terminal. In this case,
Here is the prototype of the predicate:
get_table_values_cell([+I,+J],+Table,-ContentsL)
Sample output:
?- table(sample_table4,Data),get_table_values_cell([3,2],Data,CL).
Data = [[["11"], ["21"], ["31"], ["41"]], [["12"], ["22"], ["32"]],
[["13"], ["23"]], [["14"]]],
CL = ["32"].
Thanks in advance!
The problem could be easily solved with nth0/3 or nth1/3 (built in predcates), for instance in this way:
get_table_values_cell([R,C],L):-
Data = [
[["11"], ["21"], ["31"], ["41"]],
[["12"], ["22"], ["32"]],
[["13"], ["23"]],
[["14"]]
],
nth1(R,Data,L1),
nth1(C,L1,L).
?- get_table_values_cell([3,2],CL).
CL = ["23"].
To solve it without using nth0/3 or nth1/3, you can write your own "find" (here called getElement1/4) predicate in this way:
getElement1(C,C,[H|_],H):- !. %the cut is not mandatory
getElement1(Current,Max,[_|T],Lout):-
Current < Max,
C is Current+1,
getElement1(C,Max,T,Lout).
and then
getElement([R,C],L):-
Data = [
[["11"], ["21"], ["31"], ["41"]],
[["12"], ["22"], ["32"]],
[["13"], ["23"]],
[["14"]]
],
getElement1(1,R,Data,L1),
getElement1(1,C,L1,L).
?- getElement([3,2],L).
L = ["23"]
BTW i suggest you to use built in predicates.
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.
Given this program, why am I forced to define every atom in the predicate, even if they're anonymous. Why is it that undefined variables in a dict predicate aren't thought of as anonymous?
funt2(X) :-
X = point{x:5, y:6}.
evalfunt(point{x:5, y : 6}) :-
write('hello world!').
evalfunt(point{x:_, y : _} ) :-
write('GoodBye world!').
Why can't I just say
evalfunt(point{x:5}) :-
write('GoodBye world!').
^that won't match, by the way.
I may as well just use a structure if I have to define every possible value in the dict to use dicts.
What's the motivation here? Can I do something to make my predicate terse? I'm trying to define a dict with 30 variables and this is a huge roadblock. It's going to increase my program size by a magnitude if I'm forced to define each variables (anonymous or not).
Dict is just a complex data type, like tuple, which has data AND structure. If you have, for example two facts:
fact(point{x:5, y:6}).
fact(point{x:5}).
Then the query
fact(point{x:_}).
will match the second one, but not the first one.
And the query
fact(point{x:_, y:_}).
Will match the first one, but not the second.
Now, if you want to match facts of the form fact(point{x:_, y:_, z:_}) only by one specific field, you can always write a helper rule:
matchByX(X, P) :- fact(P), P=point{x:X, y:_, z:_}.
So having facts:
fact(point{x:5, y:6, z:1}).
fact(point{x:1, y:2, z:3}).
fact(point{x:2, y:65, z:4}).
and quering
matchByX(1, P).
will return:
P = point{x:1, y:2, z:3}
UPDATE:
Moreover, in SWI-Prolog 7 version the field names can be matched as well, so it can be written in much more generic way, even for facts with different structures:
fact(point{x:5, y:6, z:1}).
fact(point{x:1, y:2}).
fact(point{x:2}).
fact(point{x:2, y:2}).
matchByField(F, X, P) :- fact(P), P.F = X.
So query:
?- matchByField(x, 2, P).
P = point{x:2} ;
P = point{x:2, y:2}.
I was able to accomplish what I needed by doing the following
checkiffive(Y) :-
get_dict(x, Y, V), V=5.
You need to use the built in methods for unifying values from a dict.
Described in chapter 5.4 of the SWI prolog reference
http://www.swi-prolog.org/download/devel/doc/SWI-Prolog-7.1.16.pdf
I have a problem to extract a specific element in DOM.
For example i use this code:
xpath(DOM, //table(1), TABLE)
and i have access to the first table. But if i try to access to the second table i use this code:
xpath(DOM, //table(2), TABLE)
but it fail and i haven't the second table.
Is it possible to select a specific node in the DOM with xpath/3?
I guess you're reusing the same variable, and that can't work:
:- [library(xpath)].
table(N, T) :-
DOM = element(xx, [],
[ element(table, [], [a,b,c]),
element(table, [], [x,y,z])
]),
xpath(DOM, //table(N), T).
with that fragment, as expected
?- table(2,T).
T = element(table, [], [x, y, z])
but
?- table(1,T), table(2,T).
false.
Selection (or predicates) in xpath are embedded in []-brackets.
For example
//table[1]
//table[2]
//table[last()-1]
//table[#someattribute='somevalue']
etc.
EDIT: It seems I missed the prolog-tag. In prolog it seems that xpath predicates are not specified by square brackets but by parenthesis: http://www.swi-prolog.org/pldoc/man?predicate=xpath%2F3 . But according to that documentation your code sample should work as intended.
I have some basic formulas like
female(camilla).
female(diana).
...
parent(person, child).
...
and predicate language/2 that specifies which predicates will I be using:
langugage(female, 1).
language(parent, 2).
What I have to do is to create predicate called body_lit/1 that returns whole clauses specified in language like this:
?- body_lit(X).
X = parent(charles, harry) ;
X = parent(diana, harry) ;
...
X = female(camilla) ;
X = female(diana) ;
...
I know I need to use call/n function and functor/3. I know how functor/3 works but I cant seem to figure out how to return the whole clause instead of just the name of the predicate.
I presume that body_lit is supposed to return all answers to predicates given in language with their arities.
body_lit(X) :- language(N,A), functor(F,N,A), call(F), X=F.
language/2 selects a predicate, functor/3 constructs an actual call from the predicate name and its arity, call/1 executes the call, and finally X=F records the call as the output argument. The last unification could have been removed:
body_lit(X) :- language(N,A), functor(X,N,A), call(X).