Status variable in Prolog - prolog

I need to code a process in which the program should run some rules base on a "Status variable", then I need to be able to change this Status variable in order to continue with the process. But I do not know if there is something like a "Status variable", any idea of how can I achieve it?

Your "status variable" could be a fact, which gets asserted (or retracted) to reflect the desired signal, although I don't think you can make such changes concurrent with a proof executing.
I think it would be cleaner to assert whatever state you need when the original process "gets stuck", and instead issue a new query when the status changes which could then use that state.

A declarative alternative to using a dynamic variable, as Scott suggested in his answer, is to use a stream variable. The idea would be to create and initialize a new stream variable, pass it (as a logic variable) to your rules, and update it with a new value when require. The rules would access (or update) at any time the current value of the stream variable. An example, using Logtalk implementation of stream variables, should make it clear (you can use Logtalk as a library with most Prolog compilers, including SWI-Prolog):
?- {library(streamvars)}.
% [ /Users/pmoura/logtalk/library/streamvars.lgt loaded ]
% (0 warnings)
true.
?- streamvars::new(SV, 1).
SV = [_G9, v(1)|_G13].
Notice that the stream variable, SV is represented by a list with a unbound tail, which allows us to add new values to it. The streamvars object provides predicates for creating a new stream variable, accessing its current value, and updating its value. A simple usage would be:
?- streamvars::new(SV, 1), streamvars::'=>'(SV, V1), streamvars::'<='(SV, 2), streamvars::'=>'(SV, V2).
SV = [v(_G31), v(1), v(2)|_G34],
V1 = 1,
V2 = 2.
The =>/2 and <=/2 predicates have corresponding operator definitions for some syntactic sugar, although those are not used above. Your rules would use these access and update predicates as necessary, with the stream variable being passed (threaded) from rule to rule.
The full documentation of the streamvars can be consulted at:
http://logtalk.org/library/streamvars_0.html
The source code can in turn be consulted at:
https://github.com/LogtalkDotOrg/logtalk3/blob/master/library/streamvars.lgt
The code is simple and you can easily adapted it to your application. A possible downside of using this implementation of stream variables is that, as shown above, all past elements are kept. If that's a problem in your case, then you will need to resort to non-declarative solutions such as using a dynamic predicate or mutables (i.e. global variables), which are provided in some Prolog systems.

Related

Prolog- Not the expected Output

I have this fact that returns the descendants but it only returns if "ascendente" is father/mother of "descendente". What am I doing wrong?
%descendenteDir(homem,mulher,filho)
descendenteDir('Tywin','Joanna','Ser Jaime').
descendenteDir('Tywin','Joanna','Cersei').
descendenteDir('Robert','Cersei','Joffrey').
descendenteDir('Robert','Cersei','Myrcella').
descendenteDir('Robert','Cersei','Tommen').
descendenteDir('Kevan','Dorna','Lancel').
descendente(Ascendente,Descendente):- descendenteDir(Ascendente,_,Descendente)
;descendenteDir(_,Ascendente,Descendente)
;descendenteDir(descendente(Ascendente,_),_,Descendente)
; descendenteDir(_,descendente(Ascendente,_),Descendente).
The descendente(Ascendente,_) part in the final rule is not quite right. It should be something like this:
descendente(Ascendente,Descendente):- descendenteDir(Ascendente,_,Descendente)
;descendenteDir(_,Ascendente,Descendente)
;descendenteDir(X,_,Descendente), descendente(Ascendente,X)
;descendenteDir(_,X,Descendente), descendente(Ascendente,X).
It's not the same as calling functions and getting returned values in languages like C++/Python/Java. In Prolog, you have a set of facts (the descendenteDir rules at the top), and some inference rules (the descendente rule). In the definition where you would use the rule recursively, you would have to provide a variable which would be bound to the values available (from the facts). That variable would later be used to infer the subsequent rules. Here X is that variable. Prolog will bind different values to it and try to infer the next part from the following clause.

Grounding head and body

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?

Using the output of functions in mathematica for further computation

Mathematica has a bevy of useful functions (Solve, NDSolve, etc.). These functions output in a very strange manner, ie {{v -> 2.05334*10^-7}}. The major issue is that there does not appear to be any way to use the output of these functions in the program; that is to say all of these appear to be terminal functions where the output is for human viewing only.
I have tired multiple methods (Part, /., etc.) to try to get the output of functions into variables so the program can use them for further steps, but nothing works. The documentation says it can be done but nothing they list actually functions. For example, if I try to use /. to move variables, it continues to treat the variable I assigned to as empty and does symbolic math with it instead of seeing the value. If I try to access the variable ie [[1]], it says the variable is not that deep.
The only method I have found is to put the later steps in separate blocks and copy-paste the output to continue evaluation. Is there any way to get the output of these functions into variables programmatically?
Solve etc. produce a list of replacement rules. So you need to apply these rules to the pattern to be replaced. For instance
solutions = x /. Solve[x^2 == 3, x]
gives you all the solutions in a list.
Here is a quick way to get variable names for the solutions:
x1 = solutions[[1]]
x2 = solutions[[2]]

In Prolog (SWI), how to build a knowledge base of user supplied pairs and assert to be equal

I am very new to Prolog and trying to learn.
For my program, I would like to have the user provide pairs of strings which are "types of".
For example, user provides at command line the strings "john" and "man". These atoms would be made to be equal, i.e. john(man).
At next prompt, then user provides "man" and "tall", again program asserts these are valid, man(tall).
Then the user could query the program and ask "Is john tall?". Or in Prolog: john(tall) becomes true by transitive property.
I have been able to parse the strings from the user's input and assign them to variables Subject and Object.
I tried a clause (where Subject and Object are different strings):
attribute(Subject, Object) :-
assert(term_to_atom(_ , Subject),
term_to_atom(_ , Object)).
I want to assert the facts that Subject and Object are valid pair. If the user asserts it, then they belong to together. How do I force this equality of the pairs?
What's the best way to go about this?
Questions of this sort have been asked a lot recently (I guess your professors all share notes or something) so a browse through recent history might have been productive for you. This one comes to mind, for instance.
Your code is pretty wide of the mark. This is what you're trying to do:
attribute(Subject, Object) :-
Fact =.. [Object, Subject],
assertz(Fact).
Using it works like this:
?- attribute(man, tall).
true.
?- tall(X).
X = man.
So, here's what you should notice about this code:
We're using =../2, the "univ" operator, to build structures from lists. This is the only way to create a fact from some atoms.
I've swapped subject and object, because doing it the other way is almost certainly not what you want.
The predicate you want is assertz/1 or asserta/1, not assert/2. The a and z on the end just tells Prolog whether you want the fact at the beginning or end of the database.
Based on looking at your code, I think you have a lot of baggage you need to shed to become productive with Prolog.
Prolog predicates do not return values. So assert(term_to_atom(... wasn't even on the right track, because you seemed to think that term_to_atom would "return" a value and it would get substituted into the assert call like in a functional or imperative language. Prolog just plain works completely differently from that.
I'm not sure why you have an empty variable in your term_to_atom predicates. I think you did that to satisfy the predicate's arity, but this predicate is pretty useless unless you have one ground term and one variable.
There is an assert/2, but it doesn't do what you want. It should be clear why assert normally only takes one argument.
Prolog facts should look like property(subject...). It is not easy to construct facts and then query them, which is what you'd have to do using man(tall). What you want to say is that there is a property, being tall, and man satisfies it.
I would strongly recommend you back up and go through some basic Prolog tutorials at this point. If you try to press forward you're only going to get more lost.
Edit: In response to your comment, I'm not sure how general you want to go. In the basic case where you're dealing with a 4-item list with [is,a] in the middle, this is sufficient:
build_fact([Subject,is,a,Object], is_a(Subject, Object)).
If you want to isolate the first and last and create the fact, you have to use univ again:
build_fact([Subject|Rest], Fact) :-
append(PredicateAtoms, [Object], Rest),
atomic_list_concat(PredicateAtoms, '_', Predicate),
Fact =.. [Predicate, Subject, Object].
Not sure if you want to live with the articles ("a", "the") that will wind up on the end though:
?- build_fact([john,could,be,a,man], Fact).
Fact = could_be_a(john, man)
Don't do variable fact heads. Prolog works best when the set of term names is fixed. Instead, make a generic place for storing properties using predefined, static term name, e.g.:
is_a(john, man).
property(man, tall).
property(john, thin).
(think SQL tables in a normal form). Then you can use simple assertz/1 to update the database:
add_property(X, Y) :- assertz(property(X, Y)).

Correct use of findall/3, especially the first template argument

i know there is a build-in function findall/3 in prolog,
and im trying to find the total numbers of hours(Thrs) and store them in a list, then sum the list up. but it doesnt work for me. here is my code:
totalLecHrs(LN,THrs) :-
lecturer(LN,LId),
findall(Thrs, lectureSegmentHrs(CC,LId,B,E,THrs),L),
sumList(L,Thrs).
could you tell me what's wrong with it? thanks a lot.
You need to use a "dummy" variable for Hours in the findall/3 subgoal. What you wrote uses THrs both as the return value for sumList/2 and as the variable to be listed in L by findall/3. Use X as the first argument of findall and in the corresponding subgoal lectureSegmentHrs/5 as the last argument.
It looks like the problem is that you're using the same variable (Thrs) twice for different things. However it's hard to tell as you've also used different capitalisation in different places. Change the findall line so that the initial variable has the same capitalisation in the lectureSegmentHrs call. Then use a different variable completely to get the final output value (ie the one that appears in sumList and in the return slot of the entire predicate).
You need to use a different variable because Prolog does not support variable reassignment. In a logical language, the notion of reassigning a variable is inherently impossible. Something like the following may seem sensible...
...
X = 10,
X = 11,
...
But you have to remember that , in Prolog is the conjunction operator. You're effectively telling Prolog to find a solution to your problem where X is both 10 and 11 at the same time. So it's obviously going to tell you that that can't be done.
Instead you have to just make up new variable names as you go along. Sometimes this does get a bit annoying but it's just goes with the territory of a logical languages.

Resources