How to stop prolog goal executing more than once? - prolog

I have a fact and a goal like below:
disconnected.
join :- disconnected, time(T), send(T).
Once this goal executes it should make disconnected false and thus not execute again. I am new to Prolog so I am a bit stuck. I am sure it's something really simple but can't figure it out at the moment. Any ideas?

You might use assert or retract to change the known facts. Or you might use global variables. I am not sure how standard that is.
The easiest would be to declare your join with two parameters: input parameter that signifies the current state, and an output parameter signifying the new state.

Related

Execute a fact if the variable of previous fact has no result

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.

Status variable in 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.

Why am I not getting a match?

I have a list structure called "stack".
At the point in my program which is causing problems, this is what stack holds:
stack([[s]],[np,[noun,john]])
I got this from running a trace, and its what stack is supposed to be holding.
When writing the next rule which is supposed to match this.
if
buffer([[Word|_]])
and aux(Word)
and stack([s],[np,[noun, john]])
If I do this then the rule executes as its supposed to. But I need to use a variable here instead of using "and stack([[s]],[np,[noun,john]])". However when I try to use anything else, the rule does not fire. I can't work out why. Other rules work fine when I use variables in the list.
Ive tried
stack([s]|Foo)
stack([s]|[Foo])
stack([MyHead]|[MyTail]... and literally every other combination I can think of.
I'm not entirely sure what is causing this problem
Your stack seems to have arity 2, where each arg is a list.
These aren't valid syntax for lists
stack([s]|Foo)
stack([s]|[Foo])
...
but since some Prolog declare the (|)/2 operator as alternative to (;)/2 (i.e. disjunction), you will not see any syntax error.
To understand you problem, you could try to unify, by mean of unification operator (=)/2
?- stack(S, Foo) = stack([[s]],[np,[noun,john]]).
you will get
S = [[s]]
Foo = [np,[noun,john]]

Can I share variables in a catch call in Prolog?

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.

Flowpattern doesn't exist

I have been working on a code in prolog for a while now and it is near compiling worthy and all my ideas seem to be solid so it should work when it compiles. It is a program that consults a database file for a list of clauses and then it awaits for a query by the user which it will then pick what information it needs from the sentence and query the database appropriately but there is a block of code that keeps giving me errors complaining that the flowpattern doesn't exist in the standard predicate this may be a silly question but even with all the looking into this I have done i can't find out how to fix this problem if someone could help me out or point me in the right direction that would be greatly appreciated.
Here is the block of code that gives the error:
loop(STR):-
scan(STR,LIST),
filter(LIST,LISroT1),
pars(LIST1,LIST2),
fail.
loop(STR):- STR >< "",readquery(L),loop(L).
readquery(QUERY):-nl,nl,write("Query: "),readln(QUERY).
scan(STR,[TOK|LIST]):-
fronttoken(STR,SYMB,STR1),!,
upper_lower(SYMB,TOK),
scan(STR1,LIST).
the specific line that the compiler complains about is fronttoken(STR,SYMB,STR),!,
any help will be apreaciated thanks!
Since we are looking at an "ex[c]er[p]t" of the code, it's hard to be sure what is going wrong, but the the given evidence points to this: loop/1 is being called before readquery/1 can do its work to populate (bind) the argument STR to loop/1.
Notice that loop/1 calls itself (recursively), and does so in a repeat/fail pattern. But the first time loop/1 runs, there's no indication in the code shown of how argument STR would get populated.
A clearer (more self-contained) code snippet would be like this:
loop :-
readquery(STR),
scan(STR,LIST),
filter(LIST,LISroT1),
pars(LIST1,LIST2),
fail.
loop :- loop.
This makes it clear that predicate loop doesn't actually return any result (and the given code snippet isn't complete enough to make clear what the program as a whole accomplishes). It assumes that the clauses ahead of fail in loop are deterministic, so that in failing, control passes through to the second (recursive) clause of loop/0. If this is not the case, the determinism could be forced by wrapping each call inside once/1.

Resources