Prolog "or" operator, query - syntax

I'm working on some prolog that I'm new to.
I'm looking for an "or" operator
registered(X, Y), Y=ct101, Y=ct102, Y=ct103.
Here's my query. What I want to write is code that will:
"return X, given that Y is equal to value Z OR value Q OR value P"
I'm asking it to return X if Y is equal to all 3 though. What's the or operator here? Is there one?

Just another viewpoint. Performing an "or" in Prolog can also be done with the "disjunct" operator or semi-colon:
registered(X, Y) :-
X = ct101; X = ct102; X = ct103.
For a fuller explanation:
Predicate control in Prolog

you can 'invoke' alternative bindings on Y this way:
...registered(X, Y), (Y=ct101; Y=ct102; Y=ct103).
Note the parenthesis are required to keep the correct execution control flow. The ;/2 it's the general or operator. For your restricted use you could as well choice the more idiomatic
...registered(X, Y), member(Y, [ct101,ct102,ct103]).
that on backtracking binds Y to each member of the list.
edit I understood with a delay your last requirement. If you want that Y match all 3 values the or is inappropriate, use instead
...registered(X, ct101), registered(X, ct102), registered(X, ct103).
or the more compact
...findall(Y, registered(X, Y), L), sort(L, [ct101,ct102,ct103]).
findall/3 build the list in the very same order that registered/2 succeeds. Then I use sort to ensure the matching.
...setof(Y, registered(X, Y), [ct101,ct102,ct103]).
setof/3 also sorts the result list

Related

How to describe commutative rules in prolog?

I intend to describe "a rule is commutative" in my database, an immediate idea is that like the code.
certain_rule(X,Y) :- X = struct(_X,Others) , Y = some_process_base_on(_X).
certain_rule(Y,X) :- X = struct(_X,Others) , Y = some_process_base_on(_X).
But if X is unbound, it will make X bind with struct(_X,Others) directly, then some_process_base_on(_X) will be unknown. Now my solution is insert compound(X) before breakdown X.
Usually, compound/1 is not strict enough, something unexpected will be taken in, functor/3 may be a better solution but too many rules will exist since too many functors I need to compare, even if I use member/2 to find functor in list I still construct too many combination.
Is there any better way to describe 'commutative', BTW, is there any better way to screen some specified structures out?
First, note that your clauses are equivalent to writing:
certain_rule(struct(X,_), some_process_base_on(X)).
certain_rule(some_process_base_on(X), struct(X,_)).
A possible solution to screen for valid structures is to use a table of valid structures. For example:
valid_structure(-) :-
!,
fail.
valid_structure(struct(_,_)).
valid_structure(some_process_base_on(_)).
...
The first clause will screen out variables while preserving first-argument indexing for the predicate. You could then define a gatekeeper predicate:
certain_rule_gatekeeper(X, Y) :-
once((valid_structure(X); valid_structure(Y))),
certain_rule(X, Y).
To address commutativity, would a definition such as the following would work in your specific case?
certain_rule_gatekeeper(X, Y) :-
once((valid_structure(X); valid_structure(Y))),
once((certain_rule(X, Y); certain_rule(Y, X))).
Sample calls using just one of the clauses above for the certain_rule/2 predicate (thus avoiding duplicated information):
| ?- certain_rule_gatekeeper(X, Y).
no
| ?- certain_rule_gatekeeper(struct(X,_), Y).
Y = some_process_base_on(X)
yes
| ?- certain_rule_gatekeeper(Y, struct(X,_)).
Y = some_process_base_on(X)
yes
| ?- certain_rule_gatekeeper(some_process_base_on(X), Y).
Y = struct(X,_)
yes
| ?- certain_rule_gatekeeper(Y, some_process_base_on(X)).
Y = struct(X,_)
yes

Prolog Array Pipe Meaning

Can anybody explain the following code? I know it returns true if X is left of Y but I do not understand the stuff with the pipe, underscore and R. Does it mean all other elements of the array except X and Y?
left(X,Y,[X,Y|_]).
left(X,Y,[_|R]) :- left(X,Y,R).
If you are ever unsure about what a term "actually" denotes, you can use write_canonical/1 to obtain its canonical representation.
For example:
| ?- write_canonical([X,Y|_]).
'.'(_16,'.'(_17,_18))
and also:
| ?- write_canonical([a,b|c]).
'.'(a,'.'(b,c))
and in particular:
| ?- write_canonical([a|b]).
'.'(a,b)
This shows you that [a|b] is the term '.'(a,b), i.e., a term with functor . and two arguments.
To reinforce this point:
| ?- [a|b] == '.'(a,b).
yes
#mat answered the original question posted quite precisely and completely. However, it seems you have a bigger question, asked in the comment, about "What does the predicate definition mean?"
Your predicate, left(X, Y, L), defines a relation between two values, X and Y, and a list, L. This predicate is true (a query succeeds) if X is immediately left of Y in the list L.
There are two ways this can be true. One is that the first two elements in the list are X and Y. Thus, your first clause reads:
left(X, Y, [X,Y|_]).
This says that X is immediately left of Y in the list [X,Y|_]. Note that we do not care what the tail of the list is, as it's irrelevant in this case, so we use _. You could use R here (or any other variable name) and write it as left(X, Y, [X,Y|R]). and it would function properly. However, you would get a singleton variable warning because you used R only once without any other references to it. The warning appears since, in some cases, this might mean you have done this by mistake. Also note that [X,Y|_] is a list of at least two elements, so you can't just leave out _ and write [X,Y] which is a list of exactly two elements.
The above clause is not the only case for X to be immediately left of Y in the list. What if they are not the first two elements in the list? You can include another rule which says that X is immediately left of Y in a list if X is immediately left of Y in the tail of the list. This, along with the base case above, will cover all the possibilities and gives a complete recursive definition of left/3:
left(X, Y, [_|R]) :- left(X, Y, R).
Here, the list is [_|R] and the tail of the list is R.
This is about the pattern matching and about the execution mechanism of Prolog, which is built around the pattern matching.
Consider this:
1 ?- [user].
|: prove(T):- T = left(X,Y,[X,Y|_]).
|: prove(T):- T = left(X,Y,[_|R]), prove( left(X,Y,R) ).
|:
|: ^Z
true.
Here prove/1 emulates the Prolog workings proving a query T about your left/3 predicate.
A query is proven by matching it against a head of a rule, and proving that rule's body under the resulting substitution.
An empty body is considered proven right away, naturally.
prove(T):- T = left(X,Y,[X,Y|_]). encodes, "match the first rule's head. There's no body, so if the matching has succeeded, we're done."
prove(T):- T = left(X,Y,[_|R]), prove( left(X,Y,R) ). encodes, "match the second rule's head, and if successful, prove its body under the resulting substitution (which is implicit)".
Prolog's unification, =, performs the pattern matching whilst instantiating any logical variables found inside the terms being matched, according to what's being matched.
Thus we observe,
2 ?- prove( left( a,b,[x,a,b,c])).
true ;
false.
3 ?- prove( left( a,b,[x,a,j,b,c])).
false.
4 ?- prove( left( a,b,[x,a,b,a,b,c])).
true ;
true ;
false.
5 ?- prove( left( a,B,[x,a,b,a,b,c])).
B = b ;
B = b ;
false.
6 ?- prove( left( b,C,[x,a,b,a,b,c])).
C = a ;
C = c ;
false.
The ; is the key that we press to request the next solution from Prolog (while the Prolog pauses, awaiting our command).

Using a univ operator in Prolog

I am trying to develop a prolog procedure that will convert numbers in any given list to a list of their square roots, using the univ (=..). So far I have
convert(X,Y): number(X), Y is X^2.
use([],_,[]).
use([_|X],convert,L):-
convert(X,Y),
L =..[convert,X,Y].
This evaluates false, what could be wrong in my logic or execution?
You could also use maplist/3 to define use/2 with convert/2 as defined in your post:
use(X,Y) :- maplist(convert, X, Y).
?- use([1,2,3],L).
L = [1,4,9]
Note that use/2 is simply failing for lists that contain anything but numbers:
?- use([1,2,3,a],L).
no
There are multiple errors:
why passing the name of the predicate convert/2?
Most important I see no recursive call!!
You ignore head element of the list by writing [_|X] which means a list with a head element and a tail X.
You try to use convert on X which is a list and assign the atom convert(X,Y) to L. Note that prolog is not a procedural language, convert(X,Y) will work only by just calling convert(X,Y) and the result will be in Y, you can't make assignments like: L = convert(X,Y) this will only assign the atom convert(X,Y) to L.
You don't need the operator =.., as a simple solution would be:
convert(X,Y):- number(X), Y is X^2.
use([],[]).
use([H|T],[Y|T1]):-
convert(H,Y),
use(T,T1).

decrement the same variable in Prolog

Something like this:
decr(X, X) :-
X is X-1.
I want to use it for decrement a number in the parent rule , if this number equal 0 for example, the parent rule return false.
Prolog is declarative: one of the properties of a declarative language is that once you set a variable, you cannot give it another value anymore. In Prolog backtracking can of course "unground" a variable and furthermore you can assign a partially grounded expression to a variable (like X=f(1,_)), but when you move deeper into the call stack, each expression can only be grounded further.
As a result: you have to use another variable. Like:
decr(X,NX) :-
NX is X-1.
This is also logical: here you defined decr(X,X) and since the argument of predicates in Prolog have no input/output direction, it is unclear whether you want to call it like decr(4,3), decr(X,3), decr(4,X) or decr(X,Y). So how can Prolog "know" that your second X is supposed to be the "new X"? It is thus a "fundamental property" of Prolog you cannot use X, call a predicate, and all of a sudden X has a different value (it can however - as said before - be grounded further, but an integer cannot be grounded further).
The reason why it will always error or fail is because, either X is not instantiated: (like decr(_,_)) in which case Prolog cannot calculate X is _-1, or you have given one of the argument a number (decr(X,3), decr(4,X) or decr(3,3)), but in that case you ask that both operands can unify (since they are both X) and are off by one at the same time, which is a contradiction.
As already mentioned, you can't reassign variables in Prolog, but the closest thing available out-of-box to what you apparently want is succ/2 predicate:
?- succ(1, X).
X = 2.
?- succ(X, 5).
X = 4.
The next closest is probably plus/3:
?- plus(1, 2, X).
X = 3.
?- plus(1, X, 3).
X = 2.
?- plus(X, 2, 3).
X = 1.

Avoiding the use of cut in Prolog absolute value predicate

I have implemented the following function in prolog with the following code:
abs2(X, Y) :- X < 0, Y is -X.
abs2(X, X) :- X >= 0, !.
How can I implement this function without the use of cut ("!")?
There's the "hidden" cut in the if-then-else construct of Prolog:
abs2(X,Y) :- X < 0 -> Y is -X ; Y = X.
It is something of a quirk, but Prolog does not backtrack on the subgoal that forms the "premise" of an if-then or if-then-else construct. Here, if X < 0 succeeds the first try, then the choice of "then" clause over "else" clause is committed (hence the description of this behavior as a "hidden" cut).
There is more of a role for a cut in the first clause of the predicate abs2/2 as written in the question. As Nicholas points out, the cut at the end of the second clause doesn't have any effect (there are no choice points left when you get there). But as Kaarel points out, there is a choice point left open if the first clause succeeds.
So what I would have written, allowing the use of a cut, is this:
abs2(X,X) :- X >= 0, !.
abs2(X,Y) :- Y is -X.
Nicholas's comments also suggest ways to "arithmetize" the absolute value (rather than use a logic definition) and avoid "cut" that way.
My prolog is a bit rusty, but why do you even need the cut? If you write the predicate properly, backtracking can't succeed, so the cut is unnecessary:
abs(X, Y) :- number(X) , X < 0 , Y is -X .
abs(X, X) :- number(X) , X >= 0 .
No need to use prolog-cut!
Simply write:
abs2(X,Y) :- Y is abs(X).

Resources