Related
I'm trying to define some operators that add the operators with the arguments and the lone arguments to a list.
So far I've defined the two operators I'm gonna use, which are OR and NEGATION, but i don't know how to specify the actions they have to do next, which are creating the lists and add the operators and arguments to it.
:- op(400,fx,neg).
:- op(500,xfx,or).
After that I'm not certain of how to add the operators and arguments to a list and make a union of all the lists.
According to the union instruction in the manual it would be something like this:
neg(X,[]) :- union([X],[neg(X)],[]).
or(X,Y,[]) :- union([X],[or(X,Y)],[]).
or(X,Y,[]) :- union([Y],[or(X,Y)],[]).
Which doesn't send any errors, but how do I make the union of all the lists and how do I specify that any lower case letter can be used for input.
An example of an imput would be:
neg(a or b).
And the expected output:
[neg(a or b), a or b, a, b]
You're running into an interesting global thing about Prolog that operators really bring to the surface, which is that operators are just another way of constructing terms.
These operator definitions of yours enable you to create terms, such as:
?- X = neg a or b.
X = neg a or b.
Endowing these terms with meaning, on the other hand, will require you to create another predicate. This is because terms in Prolog are not expressions that reduce on their own—this is partly why you need to use is/2 to reduce an arithmetic expression to a value. Even things that are purely arithmetic are just terms in Prolog:
?- X = 16*3 + 4.
X = 16*3+4.
This is not some special behavior of =/2 in Prolog. This is how terms are made. Reducing the value requires deploying another predicate:
?- X is 16*3+4.
X = 52.
So what you appear to have done is assumed that your neg operator has induced a two-argument predicate for reducing it and that your or operator has induced a three argument predicate for reducing it. Actually neither of these things has happened, all that your operator declarations do is allow you to create terms like the one above, neg a or b. So you still need to create a separate predicate for evaluating them, which is where your semantics enter the picture. So let's implement an eval/2 predicate that converts your term into the result value you want:
eval(neg X, [neg X|Result]) :-
eval(X, Result).
eval(X or Y, [X or Y|Result]) :-
eval(X, R1),
eval(Y, R2),
append(R1, R2, Result).
eval(X, [X]) :- atomic(X).
The key idea here is to match what your operators give you and peel one layer off at a time, recursively calling the rest. Our base case is "atomic values" which is to say atoms like a.
This gives us what you're looking for:
?- eval(neg (a or b), R).
R = [neg (a or b), a or b, a, b]
Note that is/2 is an operator. You could also define an operator which "does work" by declaring the operator and then supplying rules for their application. That won't help you in this case, because your examples for neg and or require you to retain structure rather than discard it. is/2, on the other hand, assumes the structure exists on the right argument and reduces it to a value for the left. You could do something similar, by say making eval/2 an operator, in which case the operator is used on the left side of the :-, like so:
[Neg X|R] eval (neg X) :- R eval X.
However, I find this kind of hard to handle and would definitely avoid it unless it ushered in more clarity.
By the way, you will most likely want to replace xfx in your op/3 call with either xfy or yfx, since constructions like a or b or c will not work with xfx due to an operator priority clash. With xfy, it will be parsed as a or (b or c) and with yfx it will be parsed as (a or b) or c which is probably more helpful. And also, if you intend always to parenthesize what you use neg with, then you do not need to declare an operator for it—the purpose of a unary operator is just to allow you to skip the parens (and control how much of what follows is consumed by it.)
Hope this helps!
I am new to using arithmetic in Prolog.
I’ve done a few small programs, but mostly involving logic. I am trying to implement a function that will return true or false if the difference between every consecutive pair of elements is the same or not.
My input would look like this: sameSeqDiffs([3, 5, 7, 9], 2)
I feel like I need to split the first two elements from the list, find their difference, and add the result to a new list. Once all the elements have been processed, check if the elements of the new list are all the same.
I’ve been taught some Prolog with building relationships and querying those, but this doesn’t seem to fit in with Prolog.
Update1: This is what I've come up with so far. I am brand new to this syntax and am still getting an error on my code, but I hope it conveys the general idea of what I'm trying to do.
diff([X,Y|Rest], Result):-
diff([Y,Z|Rest], Result2):-
Result2 = Result,
Z - Y = Result.
Update2: I know I still have much to do on this code, but here is where I will remain until this weekend, I have some other stuff to do. I think I understand the logic of it a bit more, and I think I need to figure out how to run the last line of the function only if there is at least two more things in the rest of the list to process.
diff([X,Y|Rest], Result):-
number(Y),
Y-X=Result,
diff([Rest], Result).
Update3: I believe I have the function the way I want it to. The only quirk I noticed is that when I run and input like: sameSeqDiffs([3,5,7],2).I get true returned immediately followed by a false. Is this the correct operation or am I still missing something?
sameSeqDiffs([X,Y], Result):-
A is Y - X,
A = Result.
sameSeqDiffs([X,Y,Z|T], Result):-
sameSeqDiffs([Y,Z|T], Result).
Update 4: I posted a new question about this....here is the link: Output seems to only test the very last in the list for difference function
Prolog's syntax
The syntax is a bit off: normally a clause has a head like foo(X, Y, Z), then an arrow (:-), followed by a body. That body normally does not contain any arrows :-. So the second arrow :- makes not much sense.
Predicates and unification
Secondly in Prolog predicates have no input or output, a predicate is true or false (well it can also error, or got stuck into an infinite loop, but that is typically behavior we want to avoid). It communicates answers by unifying variables. For example a call sameSeqDiffs([3, 5, 7, 9], X). can succeed by unifying X with 2, and then the predicate - given it is implemented correctly - will return true..
Inductive definitions
In order to design a predicate, on typically first aims to come up with an inductive definition: a definition that consists out of one or more base cases, and one or more "recursive" cases (where the predicate is defined by parts of itself).
For example here we can say:
(base case) For a list of exactly two elements [X, Y], the predicate sameSeqDiffs([X, Y], D) holds, given D is the difference between Y and X.
In Prolog this will look like:
sameSeqDiffs([X, Y], D) :-
___.
(with the ___ to be filled in).
Now for the inductive case we can define a sameSeqDiffs/2 in terms of itself, although not with the same parameters of course. In mathematics, one sometimes defines a function f such that for example f(i) = 2×f(i-1); with for example f(0) = 1 as base. We can in a similar way define an inductive case for sameSeqDiffs/2:
(inductive case) For a list of more than two elements, all elements in the list have the same difference, given the first two elements have a difference D, and in the list of elements except the first element, all elements have that difference D as well.
In Prolog this will look like:
sameSeqDiffs([X, Y, Z|T], D) :-
___,
sameSeqDiffs(___, ___).
Arithmetic in Prolog
A common mistake people who start programming in Prolog make is they think that, like it is common in many programming languages, Prolog add semantics to certain functors.
For example one can think that A - 1 will decrement A. For Prolog this is however just -(A, 1), it is not minus, or anything else, just a functor. As a result Prolog will not evaluate such expressions. So if you write X = A - 1, then X is just X = -(A,1).
Then how can we perform numerical operations? Prolog systems have a predicate is/2, that evaluates the right hand side by attaching semantics to the right hand side. So the is/2 predicate will interpret this (+)/2, (-)/2, etc. functors ((+)/2 as plus, (-)/2 as minus, etc.).
So we can evaluate an expression like:
A = 4, is(X, A - 1).
and then X will be set to 3, not 4-1. Prolog also allows to write the is infix, like:
A = 4, X is A - 1.
Here you will need this to calculate the difference between two elements.
You were very close with your second attempt. It should have been
samediffs( [X, Y | Rest], Result):-
Result is Y - X,
samediffs( [Y | Rest], Result).
And you don't even need "to split the first two elements from the list". This will take care of itself.
How? Simple: calling samediffs( List, D), on the first entry into the predicate, the not yet instantiated D = Result will be instantiated to the calculated difference between the second and the first element in the list by the call Result is Y - X.
On each subsequent entry into the predicate, which is to say, for each subsequent pair of elements X, Y in the list, the call Result is Y - X will calculate the difference for that pair, and will check the numerical equality for it and Result which at this point holds the previously calculated value.
In case they aren't equal, the predicate will fail.
In case they are, the recursion will continue.
The only thing missing is the base case for this recursion:
samediffs( [_], _Result).
samediffs( [], _Result).
In case it was a singleton (or even empty) list all along, this will leave the differences argument _Result uninstantiated. It can be interpreted as a checking predicate, in such a case. There's certainly no unequal differences between elements in a singleton (or even more so, empty) list.
In general, ......
recursion(A, B):- base_case( A, B).
recursion( Thing, NewThing):-
combined( Thing, Shell, Core),
recursion( Core, NewCore),
combined( NewThing, Shell, NewCore).
...... Recursion!
I have to write a predicate that takes a List and succeeds if the list contains elements "a, b, c"in that order anywhere in the list, other wise it fails. I am pretty lost on where to start(not looking for a solution, just a hint to the right direction).
Declarative wording
Almost always, when a Prolog task is formulated in a rather imperative way, the solution will be comparatively limited. This means that we typically can only use it in a few modes and directions, while other modes may even yield wrong results.
Therefore, I suggest to use more declarative wording.
You say:
a predicate that takes a list and succeeds if the list contains elements "a, b, c" in that order anywhere in the list, otherwise it fails.
That's a rather procedural way to look at this. Note that in Prolog, any argument can also be a logical variable, and thus there may not even be a list to "take". Instead, we expect the predicate to generate such lists in these cases!
Watch your wording! Very often, when you are able to express the task declaratively, an elegant and general Prolog solution will be straight-forward and often follows quite naturally from the task description.
Describing solutions
First, let us focus on what holds. There is no need to express what doesn't hold, because the predicate will not succeed anyways in such cases.
What do we want to describe?
Essentially, we want to describe lists of the form [...,a,b,c,...].
There are already some answers, with various drawbacks.
A pure way to do it uses the meta-predicate if_/3 from Indexing dif/2:
abc([X,Y,Z|Vs]) :-
if_((X=a,Y=b,Z=c), true, abc([Y,Z|Vs])).
Generality
This works in all directions. First, let us try the most general query, where the single argument is a fresh variable:
?- abc(Vs).
Vs = [a, b, c|_5032] ;
Vs = [a, b, a, b, c|_5144] ;
Vs = [a, b, a, b, a, b, c|_5286] .
Thus, we can generate solutions, which is a very nice property of a relation!
The predicate is monotonic, and therefore iterative deepening is possible to fairly enumerate answers:
?- length(Vs, _), abc(Vs).
Vs = [a, b, c] ;
Vs = [a, b, c, _11600] ;
Vs = [a, a, b, c] ;
Vs = [_11982, a, b, c],
dif(_11982, a) ;
Vs = [a, b, c, _11600, _11606] .
From this, it follows that there are no solutions with less than 3 elements. In this case, that's quite obvious. In other cases, such results may be much less obvious from the task description.
Efficiency
The predicate is deterministic if its argument is sufficiently instantiated.
For example:
?- abc([a,b,c]).
true.
?- abc([z,a,b,c]).
true.
?- abc([a,b,c,z]).
true.
Note that no choice points remain in these cases!
Here are three approaches you could take, in roughly ascending order by flexibility:
First, is to use the predicate nth0/3 to find the position of a, b, and c in the list, and then check that the position of a < position of b < position of c. For multiple instances of a, b, and c in the list (e.g. [c,b,a,b,c,a]) nth0 will find positions of each matching element in turn, such that if there are three positions that fit the criteria (even if they are not the first positions) the predicate will succeed.
Hint 1.1: The syntax for nth0 to find the position of a.
nth0(PositionA,[c,b,a,b,c,a],a)
Hint 1.2: The syntax of less than (for completeness)
PositionA < PositionB
Partial Solution 1: A sequence of commands using nth0 to check that a, b, and c appear in some order in the list [c,b,a,b,c,a] (assembling the predicate is left to you)
nth0(PositionA,[c,b,a,b,c,a],a),
nth0(PositionB,[c,b,a,b,c,a],b),
nth0(PositionC,[c,b,a,b,c,a],c),
PositionA < PositionB,
PositionB < PositionC.
Second approach uses list pattern matching - we observe that, when going down the list, we must encounter a, then b, then c. To do that, we can construct three predicates that find a, b, and c, and then pass on the rest of the list where appropriate. We must construct these predicates to ignore other elements until they see their target.
Hint 2.1: The head of a predicate where a is the first element of the list
find_a([a|Rest]) :-
Hint 2.2: The head of a predicate where anything is the first element of the list
find_a([_|Rest]) :-
Hint 2.3: When we find a, we start looking for b
find_a([a|Rest]) :-
find_b(Rest).
Hint 2.4: When we don't find a, we keep looking for a
find_a([_|Rest]) :-
find_a(Rest).
Hint 2.5: Order matters (kind-of)
If we place find_a([a|Rest]) first in the knowledge base then Prolog will always try to unify against it first, so we'll match the first a we find. If we place it second, this will still work, but with a lot of extra backtracking, and we'll find each a in reverse order.
Hint 2.6: Don't forget the base case!
Remember that, even though you don't need to do anything once you find c, you still need to create a fact stating that it is the head of the list: find_c([c|_]).
The third approach is essentially a generalised version of the second approach - instead of creating predicates to find a, b, and c, you create a predicate that finds a list of elements in order.
Hint 3.1: Your predicate should take two lists and compare the heads of each
compare([A|Targets],[B|Checks]) :-
Hint 3.2: If the same variable name appears in multiple places, it must have the same value for the predicate to match
compare([A|Targets],[A|Checks]) :- % succeeds when the same element is at the head of each list
Hint 3.3: If they match, keep going down both lists
compare(Targets,Checks).
Hint 3.4: If they don't match, only go down the Checks list
compare([A|Targets],Checks).
Hint 3.5: Never forget the base case (when there are no more targets)
compare([],_).
Hint 3.6: As before, ordering is still important
compare([A|Targets],[A|Checks]) :- ... should be in the knowledge base before compare(Targets,[_|Checks]) :- ...
Solution 3:
compare([],_).
compare([A|Targets],[A|Checks]) :-
compare(Targets,Checks).
compare(Targets,[_|Checks]) :-
compare(Targets,Checks).
Hope this helps!
Another way to describe the relation uses a grammar. You are talking about a sequence, well, that's what the dcg formalism is for!
:- set_prolog_flag(double_quotes, chars).
abcsubsequence(Cs) :-
phrase(abc, Cs).
abc -->
..., "abc", ... .
or alternatively, if you permit further text in between:
abc -->
..., "a", ..., "b", ..., "c", ... .
So what is this magic ...? It's just any sequence:
... --> [] | [_], ... .
Efficiency-wise mat's solution is much better. But for correctness reasons above versions are better since they fail for abcsequence([a,b,c|non_list]). However, making relations a tiny bit more general by permitting such solutions is quite common in Prolog, you just have to be aware of it.
Finding a,b,c
To find the letters a,b,c in a list in that order one should start with the comment by #lurker which says [X, Y, Z | T].
has_abc([a,b,c|T]).
Since I am using SWI-Prolog and prefer not to receive the warning
Warning: somecode.pl:
Singleton variables: [T]
I will make a small change by changing T to _
has_abc([a,b,c|_]).
and then run some simple test
?- has_abc([a,b,c]).
true.
?- has_abc([a,b,c,z]).
true.
?- has_abc([z,a,b,c]).
false.
As you can see the predicate has_abc can find a,b,c at the start of a list but not any place else.
Taking a list a part
In Prolog a list can be recursively deconstructed using [H|T]
deconstruct_list([Head|Tail]) :-
write('Head of list: '),write(Head),nl,
deconstruct_list(Tail).
and a few demonstration cases
?- deconstruct_list([]).
false.
?- deconstruct_list([a]).
Head of list: a
false.
?- deconstruct_list([a,b]).
Head of list: a
Head of list: b
false.
?- deconstruct_list([a,b,c]).
Head of list: a
Head of list: b
Head of list: c
false.
Putting the predicates together
Now combining the first two predicates for finding a,b,c and deconstructing a list gives us
has_abc([a,b,c|_]).
has_abc([_|T]) :-
has_abc(T).
and a few test cases
?- has_abc([]).
false.
?- has_abc([a]).
false.
?- has_abc([a,b]).
false.
?- has_abc([a,b,c]).
true .
?- has_abc([z,a,b,c]).
true .
?- has_abc([a,b,c,z]).
true .
?- has_abc([z,a,b,c,z]).
true .
Resolving the choice-point with a cut
Almost there. There is a small problem because for the true answers we had to press Enter to exit which indicates we have a choice-point.
A way to fix this is with a cut (!) which say that once we have an answer stop looking for more answers.
has_abc([a,b,c|_]) :- !.
has_abc([_|T]) :-
has_abc(T).
and a few test cases
?- has_abc([]).
false.
?- has_abc([a]).
false.
?- has_abc([a,b]).
false.
?- has_abc([a,b,c]).
true.
?- has_abc([z,a,b,c]).
true.
?- has_abc([a,b,c,z]).
true.
?- has_abc([z,a,b,c,z]).
true.
?- has_abc([d]).
false.
?- has_abc([d,e]).
false.
?- has_abc([d,e,f]).
false.
?- has_abc([d,e,f,g]).
false.
Notice that when running the test cases one did not have to press Enter to end the query.
Resolving the choice-point without a cut
See the answer by mat
I'm trying to understand the use of union (the built in predicate) in Prolog. In many cases it seems to fail when it should succeed. It seems it has something to do with the order of the elements of the lists. All of the below cases fail (they come back with "false.").
?- union([1,2,3],[],[2,3,1]).
?- union([1,5,3], [1,2], [1,5,3,2]).
?- union([4,6,2,1], [2], [1,2,4,6]).
?- union([1,2], [], [2,1]).
Shouldn't all of these be true? Any explanation as to why these cases keep failing would be very helpful.
Also: Why does the below not succeed and find the correct list for A?
?- union([1,5,3], A, [4,1,5,3,2]). /** comes back with "fail." */
There are a couple of issues here. Declarative and procedural ones. Let's start with the declarative ones, they are really sitting a bit deeper. The procedural aspects can be handled easily with appropriate programming techniques, as in this answer.
When we consider declarative properties of a predicate, we consider its set of solutions. So we pretend that all we care about is what solutions the predicate will describe. We will completely ignore how all of this is implemented. For very simple predicates, that's a simple enumeration of facts - just like a database table. It is all obvious in such situations. It becomes much more unintuitive if the set of solutions is infinite. And this happens so easily. Think of the query
?- length(Xs,1).
This harmless looking query asks for all lists of length one. All of them! Let me count - that's infinitely many!
Before we look at the actual answer Prolog produces, think what you would do in such a situation. How would you answer that query? Some of my feeble attempts
?- length(Xs,1).
Xs = [1]
; Xs = [42]
; Xs = [ben+jerry]
; Xs = [feel([b,u,r,n])]
; Xs = [cromu-lence]
; Xs = [[[]]]
; ... . % I am running out of imagination
Should Prolog produce all those infinitely many values? How much time would this take? How much time do you have to stare at walls of text? Your lifetime is clearly not enough.
Taming the number of solutions, from solutions to answers
There is a way out: The logic variable!
?- length(Xs, 1).
Xs = [_A].
% ^^
This little _A permits us to collapse all strange solutions into a single answer!
So here we really had a lot of luck: we tamed the infinity with this nice variable.
Now back to your relation. There, we want to represent sets as lists. Lists are clearly not sets per se. Consider the list [a,a] and the list [a]. While they are different, they are meant to represent the same set. Think of it: How many alternate representations are there for [a]? Yep, infinitely many. But now, the logic variable cannot help us to represent all of them compactly1. Thus we have to enumerate them one-by-one. But if we have to enumerate all those answers, practically all queries will not terminate due to infinitely many solutions to enumerate explicitly. OK, some still will:
?- union([], [], Xs).
Xs = [].
And all ground queries. And all failing queries. But once we have a variable like
?- union([a], [], Xs).
Xs = [a]
; Xs = [a,a]
; Xs = [a,a,a]
; ... .
we already are deep into non-termination.
So given that, we have to make some decisions. We somehow need to tame that infinity. One idea is to consider a subset of the actual relation that leans somehow to a side. If we want to ask questions like union([1,2],[3,4], A3) then it is quite natural to impose a subset where we have this functional dependency
A1, A2 → A3
With this functional dependency we now determine exactly one value for A3 for each pair of A1, A2. Here are some examples:
?- union([1,5,3], [1,2], A3).
A3 = [5,3,1,2].
?- union([1,2,3], [], A3).
A3 = [1,2,3].
Note that Prolog always puts a . a the end. That means Prolog says:
Dixi! I have spoken. There are no more solutions.
(Other Prologs will moan "No" at the end.) As a consequence, the queries (from your comments) now fail:
?- union([1,5,3], [1,2], [1,5,3,2]).
false.
?- union([1,2,3],[],[2,3,1]).
false.
So imposing that functional dependency now restricts the set of solutions drastically. And that restriction was an arbitrary decision of the implementer. It could have been different! Sometimes, duplicates are removed, sometimes not. If A1 and A2 both are duplicate free lists, the result A3 will be duplicate free, too.
After looking into its implementation, the following seems to hold (you do not need to do this, the documentation should be good enough - well it isn't): The elements in the last argument are structured as follows and in that order:
The elements of A1 that do not occur in A2, too. In the relative order of A1.
All elements of A2 in their original order.
So with this functional dependency further properties have been sneaked in. Such as that A2 is always a suffix of A3! Consequently the following cannot be true, because there is no suffix of A3 that would make this query true:
?- union([1,5,3], A2, [4,1,5,3,2]).
false.
And there are even more irregularities that can be described on a declarative level. Often, for the sake of efficiency, relations are too general. Like:
?- union([],non_list,non_list).
Such concerns are often swiped away by noting that we are only interested in goals with arguments that are either lists (like [a,b]) or partial lists (like [a,b|Xs]).
Anyway. We finally have now described all the declarative properties we expect. Now comes the next part: That relation should be implemented adequately! There again a new bunch of problems awaits us!
With library(lists) of SWI, I get:
?- union([1,2], [X], [1,2,3]).
false.
?- X = 3, union([1,2], [X], [1,2,3]).
X = 3.
Which is really incorrect: This can only be understood procedurally, looking at the actual implementation. This no longer is a clean relation. But this problem can be fixed!
You can avoid the correctness issues altogether by sticking to the pure, monotonic subset of Prolog. See above for more.
1) To tell the truth, it would be possible to represent that infinite set with some form of constraints. But the mere fact that there is not a single library for sets provided by current Prolog systems should make it clear that this is not an obvious choice.
I would like to know how to generate a new atom in a list based on existing atom in another list. Given list:
L=[a,b,c,d]
I would like to produce a new list, for example:
P=[a_,b_,c_,d_]
In other words something similar to string addition, e.g.
String str1 = str2 + "_";
The ISO built-in atom_concat/3 is the one to use here:
?- atom_concat(a,'_',A).
A = a_.
But how to map now the entire list element-wise? maplist/3 serves this purpose,
?- maplist(atom_concat('_'), [a,b,c,d], Xs). % Wrong!
Xs = ['_a','_b','_c','_d'].
... or almost. We added the underscore in front! maplist/3 like many other higher-order predicates adds the additional arguments at the end. In functional programming languages this is called partial application. But in our case, it would be nice to add one argument in front and one at the end. You could make your own definition, like
suffix_prefix_concat(S,P,C) :-
atom_concat(P,S,C).
while this works nicely,
?- maplist(suffix_prefix_concat('_'),[a,b,c,d], Xs).
Xs = [a_,b_,c_,d_].
... it has its own disadvantages: Inventing a new definition is often very cumbersome: Think of it, you have to figure out a new name for a single use!
A general solution to this is library(lambda) which is preinstalled in YAP, you can download it for SWI too. See the link for a generic ISO definition which works in any ISO conforming system like GNU, B, SICStus.
?- maplist(\P^C^atom_concat(P,'_',C),[a,b,c,d],Xs).
Xs = [a_,b_,c_,d_].
And since the last argument can be avoided, similarly to suffix_prefix_concat above, we can write more compactly:
?- maplist(\P^atom_concat(P,'_'),[a,b,c,d],Xs).
Xs = [a_,b_,c_,d_].
Don't know if it's available in all Prolog systems, but concat_atom/2 would do the trick:
?- concat_atom([a,'_'], A).
A = a_.