I have defined a code in PROLOG :
is_member(X, [X|_]).
is_member(X, [_|T]) :-
is_member(X, T).
I am confused by these two outputs :
out1:
is_member('a', ['b', 'c', 'd', 'a']).
>> True.
out2:
Chars = ['b', 'c', 'd', 'a'].
is_member('a', Chars).
>> Chars = [a|_2356]
Can someone help me out here? I though that output should be True.. I am trying to understand the logic here, but obviously I am lost.
Thank you for any help or advice in advance.
Here's how Prolog queries basically work.
First of all, a complete query ends with a period (.). When you execute:
Chars = [a, b, c, d].
This is a complete query since it ends in a period. When you execute a query, Prolog attempts to make it succeed via some binding of the given variables. If it is able to do so, it will simply display the variable bindings that result in success. In this particular case, the solution is trivial: Chars is bound to [a, b, c, d].
Suppose you enter the above and then you follow this with:
is_member(a, Chars).
Since the previous query completed (it ended in a period), Prolog sees this Chars as a new variable. It is no longer bound to [a, b, c, d] because the previous query ended. Prolog looks at this query and determines what binding(s) for Chars will cause it to succeed. The result is:
Chars = [a|_2356]
Prolog is telling you that a valid solution is obtained by binding Chars to the list [a|_2356] which is any list that has a as its first element. What you didn't show is that Prolog prompts for additional solutions. If you press ;, it shows you more solutions to the is_member(a, Chars). query:
3 ?- is_member(a, Chars).
Chars = [a|_5034] ;
Chars = [_5032, a|_5040] ;
Chars = [_5032, _5038, a|_5046] ;
...
In other words, is_member(a, Chars) has an infinite number of solutions. They are lists that have a as the first element, a as the second, etc.
In Prolog, if you want to establish a series of conditions that must all be true in sequence, you use a comma, not a period, to separate each condition, then end the whole thing in a period:
4 ?- Chars = [a,b,c,d], is_member(a, Chars).
Chars = [a, b, c, d] ;
false.
This query says you want to bind Chars to [a, b, c, d] and determine if a is a member of Chars. Prolog is then saying that it succeeded with one solution, Chars = [a,b,c,d]. Entering ; seeks more solutions, which comes back false since there are no additional solutions.
Let's try Isabella's other example with x:
5 ?- Chars = [a,b,c,d], is_member(x, Chars).
false.
In this case, Prolog could not find a solution, so it simply fails (showing false).
Related
I'm running some Prolog rule which uses the subtract function and in the stack trace, I found the source of error to be this:
lists:subtract([b, d | _], [b, d] , [r]) ? creep
ERROR: Out of local stack
The original call was:
member(b, X), member(d, X), subtract(X, [b, d], [r]).
and the expected output is [b, d, r].
I'm new to Prolog and unable to understand the source of error and how to fix it. Please help.
unable to understand the source of error and how to fix it.
Just take your query and look at the first two goals alone:
?- member(b, X), member(d, X).
X = [b,d|_A]
; X = [b,_A,d|_B]
; X = [b,_A,_B,d|_C]
; X = [b,_A,_B,_C,d|_D]
; X = [b,_A,_B,_C,_D,d|_E]
; ... .
Just these two goals produce already infinitely many answers. So no matter what follows, your query will never terminate. By chance, you may happen to get a solution, but more often than not you will end in some loop.
So first of all you need to fix this somehow.
Then consider the meaning of subtract/3 in SWI:
?- subtract([b,d,r], [b,d], [r]).
true.
?- subtract([b,d,X], [b,d], [r]).
false. % ?? why not X = r?
From this alone you can see that subtract/3 is not a relation. So you cannot use it as a relation like, say, append/3.
To fix this and keep as close to your original query, use library(reif) and library(lambda):
?- S1=[b,d,X], S2 = [b,d], tpartition(S2+\E^memberd_t(E,S2),S1,_,[r]).
S1 = [b,d,r], X = r, S2 = [b,d].
From SWI Prolog manual :
The library(lists) contains a number of old predicates for manipulating sets represented as unordered lists, notably intersection/3, union/3, subset/2 and subtract/3. These predicates all use memberchk/2 to find equivalent elements. As a result these are not logical while unification can easily lead to dubious results.
You are having this problem because subtract isn't pure and needs it's first two Arguments to be instantiated hence the + sign in it's documentation .
subtract(+Set, +Delete, -Result)
you can instead use union/3
union(+Set1, +Set2, -Set3)
you can know more about other mode indicators in here.
I am manipulating strings of characters in prolog, and I would like to avoid the use of too many temporary variables in my rules.
I would like to transform something like this:
process_str(Str, Next) :-
is_valid_pattern0(Pattern0),
concat(Pattern0, Tail0, Str),
concat("->", Tail1, Tail0),
is_valid_pattern1(Pattern1),
concat(Pattern1, Tail2, Tail1),
concat("|", Tail2, Next).
using a concatenation operator definition, into something like:
process_str(Pattern0.."->"..Pattern1.."|"..Next, Next) :-
is_valid_pattern0(Pattern0),
is_valid_pattern1(Pattern1).
which I believe would be far more readable, at the expense of a few more operations depending on how the operator is defined.
I found that the documentation talks about defining operators, but as far as I understand, one can only define predicate operators, not functional operators that can "return a value" (like for instance the + operator).
Please tell me either why I am wrong or how to define such a concatenation operator.
Here's a solution using DCG and term_expansion that works in SWI-Prolog. First, the basics:
:- set_prolog_flag(double_quotes, chars).
This ensures that "foo" will be interpreted as a list of three characters, not some non-standard atomic "string" object.
Then, let's assume that valid pattern0 and pattern1 matches are simply lists of letters. It's up to you to fill in the details. Some basic DCGs:
letters -->
[].
letters -->
[Letter],
{ char_type(Letter, alpha) },
letters.
pattern0 -->
letters.
pattern1 -->
letters.
For example:
?- phrase(pattern0, Pattern0).
Pattern0 = [] ;
Pattern0 = ['A'] ;
Pattern0 = ['A', 'A'] ;
Pattern0 = ['A', 'A', 'A'] ;
Pattern0 = ['A', 'A', 'A', 'A'] ;
Pattern0 = ['A', 'A', 'A', 'A', 'A'] .
?- phrase(pattern0, "helloworld").
true.
Also, the handy DCG describing simply a list:
list([]) -->
[].
list([X | Xs]) -->
[X],
list(Xs).
This doesn't seem to do much, but it will come in handy in a moment:
?- phrase(list([a, b, c]), List).
List = [a, b, c].
?- phrase(list(List), [a, b, c]).
List = [a, b, c] ;
false.
Now, you would like to define a composite pattern like Pattern0.."->"..Pattern1.."|"..Next. I suggest to write this a bit differently, namely as a list of sub-patterns: [pattern0, "->", pattern1, "|", Next]. Such a list may contain three kinds of elements:
DCG rule names
literal lists of characters
variables that may become bound to lists of characters
We can then write a DCG matching some composite patterns:
composite([]) -->
[].
composite([Head | Tail]) -->
{ atom(Head) },
% Assume that this atom is the name of another DCG rule, and execute it.
call(Head),
composite(Tail).
composite([Head | Tail]) -->
list(Head),
composite(Tail).
This expresses that a composite pattern just describes a sequence of whatever its sub-patterns describe. It only has two clauses dealing with sub-patterns: One for DCG rule names (represented by atoms) and one for character lists. The case of variables is handled automatically by the character list clause!
We can use this definition to match a character list like "foo->bar|baz" against a composite pattern:
?- phrase(composite([pattern0, "->", pattern1, "|", Next]), "foo->bar|baz").
Next = [b, a, z] ;
false.
Almost done! We can pack this up in a definition encapsulating the pattern:
process_str(Sequence, Next) :-
phrase(composite([pattern0, "->", pattern1, "|", Next]), Sequence).
This works like this:
?- process_str("foo->bar|baz", Next).
Next = [b, a, z] ;
false.
I think this is already pretty good. But if you really want a kind of pattern matching syntax, term_expansion will help. Its use is (deceptively) simple: Define a clause for term_expansion(SomeTermPattern, SomeOtherTerm), and every clause definition matching SomeTermPattern will be treated as if the programmer had written SomeOtherTerm instead. So:
term_expansion(
% Replace every definition of this form:
patterned_process_str(Pattern, Next),
% by a replacement like this:
patterned_process_str(Sequence, Next) :-
phrase(composite(Pattern), Sequence)
).
patterned_process_str([pattern0, "->", pattern1, "|", Next], Next).
We can look at Prolog's internal representation of the source code for patterned_process_str to make sure that it is as expected:
?- listing(patterned_process_str).
patterned_process_str(B, A) :-
phrase(composite([pattern0, [-, >], pattern1, ['|'], A]), B).
Variable names are lost, but otherwise our definition for patterned_process_str was expanded to the form we wanted, namely the same form that we wrote for process_str above. This definition works exactly like process_str above (since it is equivalent):
?- patterned_process_str("foo->bar|baz", Next).
Next = [b, a, z] ;
false.
Exercise: Provide an operator definition for ... Write a predicate pattern_list that converts between "dotted patterns" with .. and "list patterns", for example: pattern_list(A..B..C, [A, B, C]) should succeed. Then, expand the above term_expansion rule in a way that allows you to write patterned_process_str using the "dotted pattern" syntax directly.
You could define in your ~/.swiplrc the following pair of operators:
:- op(699,xfx,:=). % just below =
:- op(698,yfx,++). % just below :=
Out := Left ++ Right :-
flatten_expr_to_string(Left,LStrings),
flatten_expr_to_string(Right,RStrings),
atomics_to_string([LStrings,RStrings],Out).
flatten_expr_to_string(A++B,String) :-
String := A ++ B.
flatten_expr_to_string(Term,String) :-
maplist(integer,Term)
-> string_codes(String,Term)
; term_string(Term,String).
and then
?- X:=`foo`++bar++help.
X = "foobarhelp" .
?- X:=`foo`++123+bar++help.
X = "foo123+barhelp" .
Note that there is an ambiguity about lists of integers (as a backtick string is just that...). Hope you can live with that...
If you use the XPCE editor, just pull the menu [Edit \ Prolog preferences] and add the snippet there, then recompile (Ctrl+b). This will works also on Windows also, where ~/.swiplrc is named in another manner, more appropriate for the platform.
When you have defined an appropriate mini language for your strings expressions, you can explore term rewriting, to enable passing expressions to your predicates, without introducing new variables. Beware that's rather difficult to debug... you can analyze lifter in this repo to get some hints
Eg: ["c","h","a","r"] should print "char".
its atomic_list_concat(), but how would I do it for eg:
longest_common_prefix([H1,H2|T], P) :-
maplist(append(P), L, [H1,H2|T]).
Using library(double_quotes) as described here, we can use append/2 (note the 2!) :
?- set_prolog_flag(double_quotes).
true.
?- append(["c","h","a","r"], Cs).
Cs = "char".
However, please note that "c" is not a character! It is a list with one character. One single character is c alone. And most of the times, you do not need to write "c"
?- [c,h,a,r] = "char".
true.
in SWI-Prolog
?- atomic_list_concat( ["c","h","a","r"] , L).
L = char.
but things become hairier soon... you should take the time to learn about elementary data representation for anything serious
delete(X,[X|R],[_|R]).
delete(X,[F|R],[F|S]) :-
delete(X,R,S).
Above is my definition of delete predicate, for delete(X,L,R), intended to delete every occurrence of X in L with result R.
I had queried below, and get "G2397797". What does this string stand for?
?- delete(1,[1,2,3,4,5],X).
X = [_G2397797, 2, 3, 4, 5] .
If you simply correct your first clause and remove the unnecessary anonymous variable, you would get:
delete_each(X, [X|L], L).
delete_each(X, [Y|Ys], [Y|Zs]) :-
delete_each(X, Ys, Zs).
This will use unification, and delete each occurrence of X in the list upon backtracking:
?- delete_each(a, [a,b,a,c], R).
R = [b, a, c] ;
R = [a, b, c] ;
false.
Do you see how this is identical to select/3?
If you want to delete all occurrences of X in the list, you can see the answer by #coder.
In the answer you get X = [_G2397797, 2, 3, 4, 5] . , _G2397797 is not a string it is a variable that is not instantiated. This is due to the clause:
delete(X,[X|R],[_|R]).
which places in the output list an anonymous variable "_". You could write delete(X,[X|R],R).
But this has multiple problems. Firstly it only deletes the first occurrence of X not all because in the above clause when you find one you succeed. Also you haven't thought the case of empty list which is also the base case of the recursion. Finally in your second clause you haven't applied any rule that says F and X differ and this clause give wrong results when F equals to X.
So you could write:
delete(_,[],[]).
delete(X,[X|R],S):-delete(X,R,S).
delete(X,[F|R],[F|S]):-dif(X,F),delete(R,S).
I want to check if a character exists in a string. So Atom is the string and Ch the character. name is a predicate that converts the string in a list of numbers according to the ASCII code.
find_element is a predicate that is supposed to be true only if element X is part of a list. C is a counter that tells us where exactly element X was found.
This is the result I am getting:
?- exists(prolog,g). [103][112,114,111,108,111,103] false.
-------> 103 is the ASCII code of letter "g" and the list [112,114,111,108,111,103] is the list that represents the string "prolog". The question exists(prolog,g) should have provided a true response.
However the find_element predicate is working correctly. I don't understand why this is happening because when I type for example
?- find_element(5,[3,4,5,6,5,2],X).
I am getting X= 3 ; X = 5 ; false.
---->
which is absolutely fine because it tells me that 5 is the 3rd and the 5th element of the list.
So the problem is that find_element is working when I type something like ?- find_element(5,[3,4,5,6,5,2],X) but it is not when I try to call the predicate exists (which calls find_element).
This is the code:
find_element(X,[X|T],1).
find_element(X,[H|T],C):- find_element(X,T,TEMPC), C is TEMPC +1.
exists(Atom,Ch):- name(Atom,[X|T]), name(Ch,Z), write(Z), write([X|T]), find_element(Z,[X|T],Count).
Thanks in advance
I've cleaned a bit your code, and fixed a bug:
find_element(X,[X|_], 1).
find_element(X,[_|T], C) :-
find_element(X,T,TEMPC),
C is TEMPC +1.
exists(Atom, Ch):-
name(Atom, L),
name(Ch, [Z]),
find_element(Z, L, _Count).
note name(Ch, [Z]) to extract the single character. Now
?- exists(pippo,o).
true
It's worth to note that
?- find_element(3, [1,2,3,4,1,2,3,4],P).
P = 3 ;
P = 7 ;
false.
?- nth1(P, [1,2,3,4,1,2,3,4], 3).
P = 3 ;
P = 7 ;
false.
your find_element/3 behaves as nth1/3, with arguments 1 and 3 swapped.
Of course there are simpler and more general ways to perform such test. Using ISO builtins
like sub_atom/5 (a really powerful primitive for atom inspection)
?- sub_atom(pippo, _,_,_, o).
true ;
or memberchk/2, after the conversion to character lists that you already know (but using ISO builtin atom_codes/2)
exists(Atom, Ch):-
atom_codes(Atom, L),
atom_codes(Ch, [Z]),
memberchk(Z, L).
To count occurrences of a sub_atom, library(aggregate) can be used
occurences(Atom, Ch, N) :-
aggregate_all(count, sub_atom(Atom, _,_,_, Ch), N).
?- occurences(pippo, p, X).
X = 3.