I'm developing a task scheduler in Prolog. First of all let me show you a simplified version of my code. It goes like this:
handle_activable(As) :-
reset_flags,
findall(A,catch(activable(A),Exception,flag(marked_activable,A)),As),
activate_all(As).
There are two versions of activable/1 but the most relevant one is (again simplified):
activable(T) :-
task(T), /* T is a task */
inactive(T), /* The task is currently inactive */
(\+checked(T) ->
mark_checked(T),
!,
/*
Here would go the set of conditions
and statements to determine if task T
is activable or not. They may internally
call activable/1.
*/
asserta(flag(marked_activable,T))
;
/*
This task was already checked and the
result is stored in flag(marked_activable,T)
fact.
*/
throw(exception(already_checked,T))
).
The thing is that, within the "set-of-conditions-check",activable/1 might be indirectly called. That's why I need to use checked/1, in order to avoid unwanted loops.
I guessed the way I use findall/3 was okay, but since As is always instantiated as the empty list [] I'm starting to think there's something wrong with it.
The first thing I would like to ask you is the catch(...) call. Is it correct? I mean, if during an activable/1 call, the program throws an exception because the task has been already checked, would A still be instantiated (so that I can use it in flag(marked_activable,A))? If not, do you know any workaround for that?
The second thing I would like to ask you is about the correctness of my algorithm. I've been working on this for so long now and I did my best to have an efficient, robust and reliable code. The real hard thing is within the set-of-conditions check, where task's relations play a great role and create complex constrains. Do you think the way of "finding activable tasks" is a good one?
Using the built-in catch/3 predicate, the correct way for passing information is through the Catcher term.
catch(:Goal, +Catcher, :Recover)
According to SWI-Prolog doc, the Goal is the innermost goal for which Catcher unifies with the argument of throw/1, all choice points generated by Goal are cut and the system backtracks to the start of catch/3 while preserving the thrown exception term.
Thus, having a rule like:
generate(info1).
generate(info2).
generate(info3).
generate(info4).
rule(D) :-
generate(D),
...
throw(error_info(D)).
The result of catching this rule would be something like that:
?- catch(rule(D), Exception, write(Exception)).
error_info(info1).
Exception = error_info(info1).
?- catch(rule(_), error_info(E), write(E)).
info1.
E = info1.
Related
Unfortunately, I cannot give the full text of the problem for some reason. Therefore, I will try to describe the main point.
There was a murder at the hotel in room 4. 6 visitors are suspected who came to visit someone in one of the 6 hotel rooms at different intervals (These are all facts).
Then all the suspects were interviewed, some evidence was considered and information was received from the receptionist (These are the rules).
You need to find out who was where at what time. Well, and therefore who is the killer.
my problem
I am not getting the correct result.
When calling
guest(brown, R, T).
i get false (brawn must be a killer)
and basically when i call the function
solution(Guests).
then I get a very large number of lists. And the rules are not followed in them. Why is that?
result lists screenshoot
In short, I have a suspicion that these rules work somehow separately. But I could be wrong, because in the prologue I am a complete zero. What's my mistake?
P.S. If necessary, I can try to write the full text of the assignment. The only problem is that the text is in a different language from an old book that was scanned..
The reason why your query fails is the following program fragment. I obtained it by systematically generalizing away goal after goal by adding a * in front. Because this fragment fails, also your original program will fail. I am sure it will be evident to you how to interpret this:
:- op(950, fy, *). % auxiliary definition
*_.
:- initialization(guest(brown, _R, _T)). % your failing query
evidence(taylor,R,_):- *not(R=5).
evidence(white,R,_):- *not(R=5).
evidence(smith,R,_):- *not(R=1), *not(R=3), *not(R=6), *not(R=5).
evidence(green,R,_):- *not(R=3), *not(R=6).
guest(N,R,T):-
*interrogation(N,R,T),
evidence(N,R,T),
*receptionist(N,R,T).
Just a remark, instead of not(A=B) rather use dif(A,B). It's the 21st century...
I'm writing a software using SWI-Prolog where i have to find all the groundings of a predicate. In particular all the subtitutions that grounds the head and relative body supposing i can access independently head and body. Here an example of the behaviour i would like to obtain:
student(a).
student(b).
student(c).
play.
study(A):-
play,
student(A).
ground(Head,Body,Result):-
% some code
...
?- ground([study(A)],[play, student(A)],R).
R = [
[study(a):- play, student(a)],
[study(b):- play, student(b)],
[study(c):- play, student(c)]
]
And maybe generalize to:
dog(d).
dog(e).
study(A,B):-
play,
dog(B),
student(A).
?- ground([study(A,B)],[play, dog(B),student(A)],R).
R = [[study(a):- play, dog(d), student(a)] ... ]
So, for the body, find all non ground variables, ground them and then ground the head variables. Basically find all the combinations. The problem is to manage the body...
Maybe i can use for instance =../2, functor/3 and call/1 but i don't know how to takle the body (see this question/answer).
Thanks!
I am not sure why in the examples you provide the goal is inside a list and you also provide the body.
The procedure in this answer takes a goal, gets a matching clause and then gets all the solutions (binding the variables on the way). It may leave some variable unbound if they are not grounded by the goal. Upon backtracking it may take other clauses that match the initial goal.
ground(Goal, Body, LGroundClauses):-
clause(Goal, Body),
findall((Goal:-Body), call(Body), LGroundClauses).
sample run:
?- ground(study(A), Body, LClauses).
Body = (play, student(A)),
LClauses = [
(study(a):-play, student(a)),
(study(b):-play, student(b)),
(study(c):-play, student(c))
]
Note on the question and accepted solution that's a bit too long for a comment.
#gusbro writes (emphasis mine): "I am not sure why in the examples you provide the goal is inside a list and you also provide the body." I would also like to see a clarification on this point.
The ISO Prolog Core standard allows the clause/2 predicate to retrieve clauses for public predicates. But most Prolog systems, with a notably exception being SWI-Prolog, only allow using clause/2 to access clauses of dynamic predicates. Moreover, SWI-Prolog protect_static_code flag can be set to true to disable using clause/2 on static predicates. This makes the solution non-portable (and possibly undesirable in a deployment scenario) unless the predicates are declared dynamic. A possible alternative, assuming that indeed the Body argument is bound in a ground(Head,Body,Result) goal, would be to construct the clause body using the list of goals. Something like:
ground(Goal, BodyGoals, LGroundClauses):-
list_to_conjunction(BodyGoals, Body),
findall(Goal:-Body, call(Body), LGroundClauses).
This would remove the requirement of calling clause/2 and possibly making the predicates dynamic for portability. But does it make sense in your case?
Prolog's grammar uses a <head> :- <body> format for rules as such:
tree(G) :- acyclic(G) , connected(G).
, denoting status of G as a tree depends on status as acyclic and connected.
This grammar can be extended in an implicit fashion to facts. Following the same example:
connected(graphA) suggests connected(graphA):-true.
In this sense, one might loosely define Prolog facts as Prolog rules that are always true.
My question: Is in any context a bodiless rule (one that is presumed to be true under all conditions) ever appropriate? Syntactically such a rule would look as follows.
graph(X). (suggesting graph(X):-true.)
Before answering, to rephrase your question:
In Prolog, would you ever write a rule with nothing but anonymous variables in the head, and no body?
The terminology is kind of important here. Facts are simply rules that have only a head and no body (which is why your question is a bit confusing). Anonymous variables are variables that you explicitly tell the compiler to ignore in the context of a predicate clause (a predicate clause is the syntactical scope of a variable). If you did try to give this predicate clause to the Prolog compiler:
foo(Bar).
you will get a "singleton variable" warning. Instead, you can write
foo(_).
and this tells the compiler that this argument is ignored on purpose, and no variable binding should be attempted with it.
Operationally, what happens when Prolog tries to prove a rule?
First, unification of all arguments in the head of the rule, which might lead to new variable bindings;
Then, it tries to prove the body of the rule using all existing variable bindings.
As you can see, the second step makes this a recursively defined algorithm: proving the body of a rule means proving each rule in it.
To come to your question: what is the operational meaning of this:
foo(_).
There is a predicate foo/1, and it is true for any argument, because there are no variable bindings to be done in the head, and always, because no subgoals need to be proven.
I have seen at least one use of such a rule: look at the very bottom of this section of the SWI-Prolog manual. The small code example goes like this:
term_expansion(my_class(_), Clauses) :-
findall(my_class(C),
string_code(_, "~!##$", C),
Clauses).
my_class(_).
You should read the linked documentation to see the motivation for doing this. The purpose of the code itself is to add at compile time a table of facts to the Prolog database. This is done by term expansion, a mechanism for code transformations, usually used through term_expansion/2. You need the definition of my_class/1 so that term_expansion/2 can pick it up, transform it, and replace it with the expanded code. I strongly suggest you take the snipped above, put it in a file, consult it and use listing/1 to see what is the effect. I get:
?- listing(my_class).
my_class(126).
my_class(33).
my_class(64).
my_class(35).
my_class(36).
true.
NB: In this example, you could replace the two occurrences of my_class(_) with anything. You could have just as well written:
term_expansion(foobar, Clauses) :-
findall(my_class(C),
string_code(_, "~!##$", C),
Clauses).
foobar.
The end result is identical, because the operational meaning is identical. However, using my_class(_) is self-documenting, and makes the intention of the code more obvious, at least to an experienced Prolog developer as the author of SWI-Prolog ;).
A fact is just a bodiless rule, as you call it. And yes, there are plenty of use cases for bodiless facts:
representing static data
base cases for recursion
instead of some curly brace language pseudo code
boolean is_three(integer x) {
if (x == 3) { return true; }
else { return false; }
}
we can simply write
is_three(3).
This is often how the base case of a recursive definition is expressed.
To highlight what I was initially looking for, I'll include the following short answer for those who might find themselves asking my initial question in the future.
An example of a bodiless rule is, as #Anniepoo suggested, a base case for a recursive definition. Look to the example of a predicate, member(X,L) for illustration:
member(X,[X|T]). /* recursive base case*/
member(X,[H|T]):- member(X,T).
Here, the first entry of the member rule represents a terminating base case-- the item of interest X matching to the head of the remaining list.
I suggest visiting #Boris's answer (accepted) for a more complete treatment.
I am implementing a Prolog program for trigonometric identities. This is a part of the program.
simplify_exp(Term1+Term2,X,Y) :- isolaxt(Term1+Term2,Y),
(nonvar(Y)-> simplify_exp(Term1,X,Y), simplify_exp(Term2,X,Y)).
isolaxt(sin(U)^2+cos(U)^2,1).
I want to execute the if statement only if Y has no value (when isolaxt is failed only). Even though I included nonvar(Y) it didn't work. How can it be done?
I don't really get if that's the only isolaxt clause you have or if you included it to exemplify.
Anyway, if isolaxt fails then simplify_exp will fail without reaching nonvar(Y).
Is that the behavior you expect? Perhaps you meant to use ; like so:
simplify_exp(Term1+Term2,X,Y) :-
isolaxt(Term1+Term2,Y); (simplify_exp(Term1,X,Y), simplify_exp(Term2,X,Y)).
This means either isolaxt will succeed or you're going to proceed with the calls to simplify_exp.
Also, note that nonvar(Y) will fail when isolaxt succeeds, so maybe you expected to use var(Y) instead.
I'm working on a college assignment where I must verify if a certain clause (as a fact or as a rule) exists in the current clause database.
The idea is to use a rule whose head is verify(+name, +arguments). This rule should be true if in the database exists another rule whose head is name(arguments)
Any help would be greatly appreciated...
Using call/1 is not a good idea because call/1 actually calls the goal, but you just want to find out if the fact/rule exists, and you don't want to wait after a long calculation that the call might trigger, and you don't want to have something printed on the screen if the called rule in turn calls e.g. writeln/1. In addition, you would want verify/2 to succeed even if the call failed (but the fact/rule is otherwise there).
As a solution, SWI-Prolog offers callable/1
callable(+Term)
True if Term is bound to an atom or a compound term,
so it can be handed without type-error to call/1, functor/3 and =../2.
Here are two version of verify/2, one using call/1 and the other using callable/1.
verify1(Name, Arguments) :-
Term =.. [Name | Arguments],
call(Term).
verify2(Name, Arguments) :-
Term =.. [Name | Arguments],
callable(Term).
father(abraham, isaac) :-
writeln('hello').
father(abraham, adam) :-
fail.
Are you familiar with the concept of unification? What you have to do is: just call a predicate that looks like the one you're trying to find.
So, say in your database is:
father(abraham,isaac).
Now you want to call something like:
verify(father,[abraham,isaac]).
Your predicate body will then have to contain a mechanism of calling father(abraham,isaac). which should then return true. Calling father(abraham,adam) should fail.
You will need two predicates for this: =../2 and call/2. If you are using SWI-Prolog, call help(=..). and help(call) from the interpreter's command line to access the documentation.
I hope I didn't spoil the assignment for you. You still have to find out what to do with partially instantiated predicates (so, say something like verify(father,[abraham,X]). on your own, but it shouldn't be hard from here.
Good luck.