Related
So, my goal is to make a map colourer in Prolog. Here's the map I'm using:
And this are my colouring constraints:
colouring([A,B,C,D,E,F]) :-
maplist( #\=(A), [B,C,D,E] ),
maplist( #\=(B), [C,D,F]),
C #\= D,
maplist( #\=(D), [E,F]),
E #\= F.
Where [A,B,C,D,E,F] is a list of numbers(colors) from 1 to n.
So I want my solver to, given a List of 6 colors and a natural number N, determine the colors and N constraints both ways, in a way that even the most general query could yield results:
regions_ncolors(L,N) :- colouring(L), L ins 1..N, label(L).
Where the most general query is regions_ncolors(L,N).
However, the operator ins doesn't seem to accept a variable N, it instead yields an argument not sufficiently instantiated error. I've tried using this solution instead:
int_cset_(N,Acc,Acc) :- N #= 0.
int_cset_(N,Acc,Cs) :- N_1 #= N-1, int_cset_(N_1,[N|Acc],Cs).
int_cset(N,Cs) :- int_cset_(N,[],Cs).
% most general solver
regions_ncolors(L,N) :- colouring(L), int_cset(N,Cs), subset(L,Cs), label(L).
Where the arguments in int_cset(N,Cs) is a natural number(N) and the counting set Sn = {1,2,...,N}
But this solution is buggy as regions_ncolors(L,N). only returns the same(one) solution for all N, and when I try to add a constraint to N, it goes in an infinite loop.
So what can I do to make the most general query work both ways(for not-instantiated variables)?
Thanks in advance!
Btw, I added a swi-prolog tag in my last post although it was removed by moderation. I don't know if this question is specific to swi-prolog which is why I'm keeping the tag, just in case :)
Your colouring is too specific, you encode the topology of your map into it. Not a problem as is, but it defeats of the purpose of then having a "most general query" solution for just any list.
If you want to avoid the problem of having a free variable instead of a list, you could first instantiate the list with length/2. Compare:
?- L ins 1..3.
ERROR: Arguments are not sufficiently instantiated
ERROR: In:
ERROR: [16] throw(error(instantiation_error,_86828))
ERROR: [10] clpfd:(_86858 ins 1..3) ...
Is that the same problem as you see?
If you first make a list and a corresponding set:
?- length(L, N), L ins 1..N.
L = [],
N = 0 ;
L = [1],
N = 1 ;
L = [_A, _B],
N = 2,
_A in 1..2,
_B in 1..2 ;
L = [_A, _B, _C],
N = 3,
_A in 1..3,
_B in 1..3,
_C in 1..3 .
If you use length/2 like this you will enumerate the possible lists and integer sets completely outside of the CLP(FD) labeling. You can then add more constraints on the variables on the list and if necessary, use labeling.
Does that help you get any further with your problem? I am not sure how it helps for the colouring problem. You would need a different representation of the map topology so that you don't have to manually define it within a predicate like your colouring/1 you have in your question.
There are several issues in your program.
subset/2 is impure
SWI's (by default) built-in predicate subset/2 is not the pure relation you are hoping for. Instead, it expects that both arguments are already sufficiently instantiated. And if not, it takes a guess and sticks to it:
?- colouring(L), subset(L,[1,2,3,4,5]).
L = [1,2,3,4,2,1].
?- colouring(L), subset(L,[1,2,3,4,5]), L = [2|_].
false.
?- L = [2|_], colouring(L), subset(L,[1,2,3,4,5]), L = [2|_].
L = [2,1,3,4,1,2].
With a pure definition it is impossible that adding a further goal as L = [2|_] in the third query makes a failing query succeed.
In general it is a good idea to not interfere with labeling/2 except for the order of variables and the options argument. The internal implementation is often much faster than manual instantiations.
Also, your map is far too simple to expose subset/2s weakness. Not sure what the minimal failing graph is, but here is one such example from
R. Janczewski et al. The smallest hard-to-color graph for algorithm DSATUR, Discrete Mathematics 236 (2001) p.164.
colouring_m13([K1,K2,K3,K6,K5,K7,K4]):-
maplist(#\=(K1), [K2,K3,K4,K7]),
maplist(#\=(K2), [K3,K5,K6]),
maplist(#\=(K3), [K4,K5]),
maplist(#\=(K4), [K5,K7]),
maplist(#\=(K5), [K6,K7]),
maplist(#\=(K6), [K7]).
?- colouring_m13(L), subset(L,[1,2,3,4]).
false. % incomplete
?- L = [3|_], colouring_m13(L), subset(L,[1,2,3,4]).
L = [3,1,2,2,3,1,4].
int_cset/2 never terminates
... (except for some error cases like int_cset(non_integer, _).). As an example consider:
?- int_cset(1,Cs).
Cs = [1]
; loops.
And don't get fooled by the fact that an actual solution was found! It still does not terminate.
#Luis: But how come? I'm getting baffled by this, the same thing is happening on ...
To see this, you need the notion of a failure-slice which helps to identify the responsible part in your program. With some falsework consisting of goals false the responsible part is exposed.
All unnecessary parts have been removed by false. What remains has to be changed somehow.
int_cset_(N,Acc,Acc) :- false, N #= 0.
int_cset_(N,Acc,Cs) :- N1 #= N-1, int_cset_(N1,[N|Acc],Cs), false.
int_cset(N,Cs) :- int_cset_(N,[],Cs), false.
?- int_cset(1, Cs), false.
loops.
Adding the redundant goal N1 #> 0
will avoid unnecessary non-termination.
This alone will not solve your problem since if N is not given, you will still encounter non-termination due to the following failure slice:
regions_ncolors(L,N) :-
colouring(L),
int_cset(N,Cs), false,
subset(L,Cs),
label(L).
In int_cset(N,Cs), Cs occurs for the first time and thus cannot influence termination (there is another reason too, its definition would ignore it as well..) and therefore only N has a chance to induce termination.
The actual solution has been already suggested by #TA_intern using length/2 which liberates one of such mode-infested chores.
I am trying to build a simple predicate which get as inputs two lists and the results is a third one consisting of the intersection of the first two.
I have decided to do using logical statement. I am pretty sure my logic is correct but my predicate is not working. Any ideas?:
element(X,[H|T]) :-
X=H
;
element(X,T).
intersection(L1,L2,R) :-
not((
element(A,L1),
not(element(A,L2))
)),
not((
element(A,L1),
not(element(A,R))
)).
Please do not post alternative methods I am wondering why this one returns FALSE every time.
Your definition is correct too general. It admits e.g. that [] is the intersection of any two lists which is too general. I.e. it incorrectly succeeds for intersection([],[a],[a]). It lacks a third "for all" idiom stating that all elements that are in both lists will be in the resulting list.
But otherwise your definition is fine. For the ground case. What is a bit unusual is that the intersection is the first and not the last argument. Quite irritating to me are the variable names. I believe that R means "result", thus the intersection. And L1 and L2 are the two sets to build the intersection.
It is a bit too general, though - like many Prolog predicates - think of append([], non_list, non_list). Apart from lists, your definition admits also terms that are neither lists nor partial lists:
?- intersection(non_list1,[1,2|non_list2],[3,4|non_list3]).
To make it really useful safe, use it like so:
?- when(ground(intersection(I, A, B)), intersection(I, A, B)).
or so:
?- ( ground(intersection(I, A, B))
-> intersection(I, A, B)
; throw(error(instantiation_error, intersection(I, A, B)))
).
Or, using iwhen/2:
?- iwhen(ground(intersection(I, A, B)), intersection(I, A, B) ).
As a minor remark, rather write (\+)/1 in place of not/1.
The problem is that not/1 merely negates the outcome of your element/2. It doesn't cause element/2 to backtrack to find other instantiations for which the enclosing not/1 will be true.
Consider the following program.
a(1).
a(2).
b(1).
b(2).
b(3).
And the following queries:
b(X), not(a(X)).
not(a(X)), b(X).
The first one yields X = 3 while the second one yields false. That is because the first query first instantiates X with 1, then with 2, then with 3, until finally not(a(X)) succeeds.
The second query first instantiates X with 1, a(1) succeeds, so not(a(1)) fails. There is no backtracking done!
The lack of backtracking due to negation as pointed out by #SQB is actually not the only problem with your code. If you play around a little with ground queries you find that non-lists and the empty list as pointed out by #false are also not the only issue. Consider the following queries:
?- intersection([2,3],[1,2,3],[2,3,4]).
yes
?- intersection([2],[1,2,3],[2,3,4]).
yes
?- intersection([3],[1,2,3],[2,3,4]).
yes
?- intersection([],[1,2,3],[2,3,4]).
yes
The first is what usually is understood as intersection. The other three are all sublists of the intersection including the trivial sublist []. This is due to the way the predicate describes what an intersection is: In an intersection is not the case that an element is in the first but not the second list AND that said element is in the first but not the third list. This description clearly fits the three above queries hence they succeed. Fooling around a little more with this description in mind there are some other noteworthy ground queries that succeed:
?- intersection([2,2,3],[1,2,3],[2,3,4]).
yes
The question whether the presence of duplicates in the solution is acceptable or not is in fact quite a matter of debate. The lists [2,2,3] and [2,3] although different represent the same set {2,3}. There is this recent answer to a question on Prolog union that is elaborating on such aspects of answers. And of course the sublists of the intersection mentioned above can also contain duplicates or multiples:
?- intersection([2,2,2],[1,2,3],[2,3,4]).
yes
But why is this? For the empty list this is quite easy to see. The query
?- element(A,[]).
no
fails hence the conjunction element(A,L1), not(element(A,L2)) also fails for L1=[]. Therefore the negation wrapped around it succeeds. The same is true for the second negation, consequently [] can be derived as intersection. To see why [2] and [3] succeed as intersection it is helpful to write your predicate as logic formula with the universal quantifiers written down explicitly:
∀L1∀L2∀R∀A (intersection(L1,L2,R) ← ¬ (element(A,L1) ∧ ¬ element(A,L2)) ∧ ¬ (element(A,L1) ∧ ¬ element(A,R)))
If you consult a textbook on logic or one on logic programming that also shows Prolog code as logic formulas you'll find that the universal quantifiers for variables that do not occur in the head of the rule can be moved into the body as existential quantifiers. In this case for A:
∀L1∀L2∀R (intersection(L1,L2,R) ← ∃A ( ¬ (element(A,L1) ∧ ¬ element(A,L2)) ∧ ¬ (element(A,L1) ∧ ¬ element(A,R))))
So for all arguments L1,L2,R there is some A that satisfies the goals. Which explains the derivation of the sublists of the intersection and the multiple occurrences of elements.
However, it is much more annoying that the query
?- intersection(L1,[1,2,3],[2,3,4]).
loops instead of producing solutions. If you consider that L1 is not instantiated and look at the results for the following query
?- element(A,L1).
L1 = [A|_A] ? ;
L1 = [_A,A|_B] ? ;
L1 = [_A,_B,A|_C] ? ;
...
it becomes clear that the query
?- element(A,L1),not(element(A,[1,2,3])).
has to loop due to the infinitely many lists L1, that contain A, described by the first goal. Hence the corresponding conjunction in your predicate has to loop as well. Additionally to producing results it would also be nice if such a predicate mirrored the relational nature of Prolog and worked the other way around too (2nd or 3rd arguments variable). Let's compare your code with such a solution. (For the sake of comparison the following predicate describes sublists of the intersection just as your code does, for a different definition see further below.)
To reflect its declarative nature lets call it list_list_intersection/3:
list_list_intersection(_,_,[]).
list_list_intersection(L1,L2,[A|As]) :-
list_element_removed(L1,A,L1noA),
list_element_removed(L2,A,L2noA),
list_list_intersection(L1noA,L2noA,As).
list_element_removed([X|Xs],X,Xs).
list_element_removed([X|Xs],Y,[X|Ys]) :-
dif(X,Y),
list_element_removed(Xs,Y,Ys).
Like your predicate this version is also using the elements of the intersection to describe the relation. Hence it's producing the same sublists (including []):
?- list_list_intersection([1,2,3],[2,3,4],I).
I = [] ? ;
I = [2] ? ;
I = [2,3] ? ;
I = [3] ? ;
I = [3,2] ? ;
no
but without looping. However, multiple occurrences are not produced anymore as already matched elements are removed by list_element_removed/3. But multiple occurrences in both of the first lists are matched correctly:
?- list_list_intersection([1,2,2,3],[2,2,3,4],[2,2,3]).
yes
This predicate also works in the other directions:
?- list_list_intersection([1,2,3],L,[2,3]).
L = [2,3|_A] ? ;
L = [2,_A,3|_B],
dif(_A,3) ? ;
L = [2,_A,_B,3|_C],
dif(_A,3),
dif(_B,3) ? ;
...
?- list_list_intersection(L,[2,3,4],[2,3]).
L = [2,3|_A] ? ;
L = [2,_A,3|_B],
dif(_A,3) ? ;
L = [2,_A,_B,3|_C],
dif(_A,3),
dif(_B,3) ? ;
...
So this version corresponds to your code without the duplicates. Note how the element A of the intersection explicitly appears in the head of the rule where all elements of the intersection are walked through recursively. Which I believe is what you tried to achieve by utilizing the implicit universal quantifiers in front of Prolog rules.
To come back to a point in the beginning of my answer, this is not what is commonly understood as the intersection. Among all the results list_list_intersection/3 describes for the arguments [1,2,3] and [2,3,4] only [2,3] is the intersection. Here another issue with your code comes to light: If you use the elements of the intersection to describe the relation, how do you make sure you cover all intersecting elements? After all, all elements of [2] occur in [1,2,3] and [2,3,4]. An obvious idea would be to walk through the elements of one of the other lists and describe those occurring in both as also being in the intersection. Here is a variant using if_/3 and memberd_t/3:
list_list_intersection([],_L2,[]).
list_list_intersection([X|Xs],L2,I) :-
if_(memberd_t(X,L2),
(I=[X|Is],list_element_removed(L2,X,L2noX)),
(I=Is,L2noX=L2)),
list_list_intersection(Xs,L2noX,Is).
Note that it is also possible to walk through the arguments of the second list instead of the first one. The predicate memberd_t/3 is a reified variant of your predicate element/2 and list_element_removed/3 is again used in the description to avoid duplicates in the solution. Now the solution is unique
?- list_list_intersection([1,2,3],[2,3,4],L).
L = [2,3] ? ;
no
and the "problem queries" from above fail as expected:
?- list_list_intersection([1,2,3],[2,3,4],[]).
no
?- list_list_intersection([1,2,3],[2,3,4],[2]).
no
?- list_list_intersection([1,2,3],[2,3,4],[3]).
no
?- list_list_intersection([1,2,3],[2,3,4],[2,2,3]).
no
?- list_list_intersection([1,2,3],[2,3,4],[2,2,2]).
no
And of course you can also use the predicate in the other directions:
?- list_list_intersection([1,2,3],L,[2,3]).
L = [2,3] ? ;
L = [3,2] ? ;
L = [2,3,_A],
dif(_A,1) ? ;
...
?- list_list_intersection(L,[2,3,4],[2,3]).
L = [2,3] ? ;
L = [2,3,_A],
dif(4,_A) ? ;
...
I experience some issues when I'm training prolog exercises,the problem below is,
The predicate defines what it means to be a tree, and can be used to test whether a term is a tree:
tree(t(L,R)) :- tree(L), tree(R).
tree(T) :- T\=t(_ , _).
By using this predicate you can find an element in a tree, (called a leaf):
leaf(t(L,R),E) :- leaf(L,E); leaf(R,E).
leaf(T,T) :- T\=t(_ , _).
So here have two problem, first is write predicate elements/2 that produces a list of the elements as they are found in the leafs of a tree in the first argument in a left-to-right order!
The second is write a predicate same content/2 that succeeds exactly when two trees contain the same elements in the same order! Duplicates are significant.
Hope can get anyone good at prolog can help me, thanks a lot.
Both tree/1 and leaf/1 are defaulty1,2!
Why not use a cleaner representation like this?
is_tree(leaf(_)).
is_tree(bin(L,R)) :-
is_tree(L),
is_tree(R).
Note that:
is_tree/1 is more versatile than tree/1 and leaf/1: it can generate as well as test trees—and even do a little of both (if the argument is partially instantiated).
is_tree/1 never gives logically unsound answers—no matter which "mode" it is used in.
Some sample uses of is_tree/1:
?- is_tree(T). % generate
T = leaf(_A)
; T = bin(leaf(_A),leaf(_B))
; T = bin(leaf(_A),bin(leaf(_B),leaf(_C)))
; T = bin(leaf(_A),bin(leaf(_B),bin(leaf(_C),leaf(_D))))
...
?- is_tree(bin(leaf(1),bin(leaf(2),3))). % test
false.
?- is_tree(bin(leaf(1),bin(leaf(2),leaf(3)))). % test
true.
?- T = bin(bin(leaf(1),2),_), is_tree(T). % do both (or at least try)
false.
?- T = bin(bin(leaf(1),leaf(2)),_), is_tree(T). % do both
T = bin(bin(leaf(1),leaf(2)),leaf(_A))
T = bin(bin(leaf(1),leaf(2)),bin(leaf(_A),leaf(_B)))
T = bin(bin(leaf(1),leaf(2)),bin(leaf(_A),bin(leaf(_B),leaf(_C))))
...
Coming back to your question on how to implement elements/2 and content/2... Use dcg!
leaves(leaf(E)) --> [E].
leaves(bin(L,R)) --> leaves(L), leaves(R).
same_content(A,B) :-
phrase(leaves(A),Ls),
phrase(leaves(B),Ls).
Sample query:
?- same_content(bin(leaf(1),bin(leaf(2),leaf(3))),
bin(bin(leaf(1),leaf(2)),leaf(3))).
true.
Footnote 1: This rock-solid treatise on teaching Prolog discusses many common obstacles, including defaultyness.
Footnote 2: In this answer #mat explains on how defaultyness in Prolog impedes declarative debugging and reasoning.
I'm new in Prolog and I was trying to solve sucha problem so i wish if anybody could help.
I want to implement a ternary predicate flatten_term(Term, Function_symbol, Flattened_term)
that succeeds if Flattened_term is obtained from Term by flattening out all
nested occurrences of Function_symbol. It is assumed that Term contains no
Prolog variables and no lists without checking the list.
?- flatten_term(f(f(x)), f, Flattened_term).
Flattened_term = f(x).
?- flatten_term(f(x), f, Flattened_term).
Flattened_term = f(x).
?- flatten_term(a, f, Flattened_term).
Flattened_term = a.
?- flatten_term(g(f(x)), f, Flattened_term).
Flattened_term = g(f(x)).
?- flatten_term(g(f(f(x))), f, Flattened_term).
Flattened_term = g(f(x)).
I'm using the code below in order to count the items in a term. Maybe this is similar to what you are looking for?
?- flatten_term(5+3*x=10,List).
List = [=, +, 5, *, 3, x, 10].
This is the source code:
flatten_term(Term,[Term]):-
atomic(Term),!.
flatten_term(Term,Flat):-
Term =.. TermList,
flatten_term_list(TermList,Flat),!.
flatten_term_list([],[]):-!.
flatten_term_list([H|T],List):-
flatten_term(H,HList),
flatten_term_list(T,TList),
append(HList,TList,List),!.
As noted, you really should show an example of your work. But, here's a few hints for you to get you started:
Flattening a list-of-lists like [a,[b,c],d,[e,[f,g,h]]] is just a simple recursive tree walk. There are several questions here on Stack Overflow that demonstrate how to do this, For instance, this question, How to implement flatten list in prolog ,with tail recursion?
There are a number of predicates concerning type checking and the analysis, construction and decomposition of terms:
http://www.swi-prolog.org/pldoc/man?section=typetest
http://www.swi-prolog.org/pldoc/man?section=manipterm
In particular, compound terms can be decomposed to a list using the univ operator =../2:
foo(alpha,bravo,charlie) =.. L
which yields L = [foo,alpha,bravo,charlie].
One should also note that '=../2` is used to convert a list into a compound term:
T =.. [foo,alpha,bravo,charlie]
which yields, as one might expect T = foo(alpha,bravo,charlie).
Good luck!
I have a manually made DCG rule to select idiomatic phrases
over single words. The DCG rule reads as follows:
seq(cons(X,Y), I, O) :- noun(X, I, H), seq(Y, H, O), \+ noun(_, I, O).
seq(X) --> noun(X).
The first clause is manually made, since (:-)/2 is used instead
of (-->)/2. Can I replace this manually made clause by
some clause that uses standard DCG?
Best Regards
P.S.: Here is some test data:
noun(n1) --> ['trojan'].
noun(n2) --> ['horse'].
noun(n3) --> ['trojan', 'horse'].
noun(n4) --> ['war'].
And here are some test cases, the important test case is the first test case, since it does only
deliver n3 and not cons(n1,n2). The behaviour of the first test case is what is especially desired:
?- phrase(seq(X),['trojan','horse']).
X = n3 ;
No
?- phrase(seq(X),['war','horse']).
X = cons(n4,n2) ;
No
?- phrase(seq(X),['trojan','war']).
X = cons(n1,n4) ;
No
(To avoid collisions with other non-terminals I renamed your seq//1 to nounseq//1)
Can I replace this manually made clause by some clause that uses standard DCG?
No, because it is not steadfast and it is STO (details below).
Intended meaning
But let me start with the intended meaning of your program. You say you want to select idiomatic phrases over single words. Is your program really doing this? Or, to put it differently, is your definition really unique? I could now construct a counterexample, but let Prolog do the thinking:
nouns --> [] | noun(_), nouns.
?- length(Ph, N), phrase(nouns,Ph),
dif(X,Y), phrase(nounseq(X),Ph), phrase(nounseq(Y),Ph).
Ph = [trojan,horse,trojan], N = 3, X = cons(n1,cons(n2,n1)), Y = cons(n3,n1)
; ...
; Ph = [trojan,horse,war], N = 3, X = cons(n3,n4), Y = cons(n1,cons(n2,n4))
; ... .
So your definition is ambiguous. What you essentially want (probably) is some kind of rewrite system. But those are rarely defined in a determinate manner. What, if two words overlap like an additional noun(n5) --> [horse, war]. etc.
Conformance
A disclaimer up-front: Currently, the DCG document is still being developed — and comments are very welcome! You find all material in this place. So strictly speaking, there is at the current point in time no notion of conformance for DCG.
Steadfastness
One central property a conforming definition must maintain is the property of steadfastness. So before looking into your definition, I will compare two goals of phrase/3 (running SWI in default mode).
?- Ph = [], phrase(nounseq(cons(n4,n4)),Ph0,Ph).
Ph = [], Ph0 = [war,war]
; false.
?- phrase(nounseq(cons(n4,n4)),Ph0,Ph), Ph = [].
false.
?- phrase(nounseq(cons(n4,n4)),Ph0,Ph).
false.
Moving the goal Ph = [] at the end, removes the only solution. Therefore, your definition is not steadfast. This is due to the way how you handle (\+)/1: The variable O must not occur within the (\+)/1. But on the other hand, if it does not occur within (\+)/1 you can only inspect the beginning of a sentence. And not the entire sentence.
Subject to occurs-check property
But the situation is worse:
?- set_prolog_flag(occurs_check,error).
true.
?- phrase(nounseq(cons(n4,n4)),Ph0,Ph).
ERROR: noun/3: Cannot unify _G968 with [war|_G968]: would create an infinite tree
So your program relies on STO-unifications (subject-to-occurs-check unifications) whose outcome is explicitly undefined in
ISO/IEC 13211-1 Subclause 7.3.3 Subject to occurs-check (STO) and not subject to occurs-check (NSTO)
This is rather due to your intention to define the intersection of two non-terminals. Consider the following way to express it:
:- op( 950, xfx, //\\). % ASCII approximation for ∩ - 2229;INTERSECTION
(NT1 //\\ NT2) -->
call(Xs0^Xs^(phrase(NT1,Xs0,Xs),phrase(NT2,Xs0,Xs))).
% The following is predefined in library(lambda):
^(V0, Goal, V0, V) :-
call(Goal,V).
^(V, Goal, V) :-
call(Goal).
Already with this definition we can get into STO situations:
?- phrase(([a]//\\[a,b]), Ph0,Ph).
ERROR: =/2: Cannot unify _G3449 with [b|_G3449]: would create an infinite tree
In fact, when using rational trees we get:
?- set_prolog_flag(occurs_check,false).
true.
?- phrase(([a]//\\[a,b]), Ph0,Ph).
Ph0 = [a|_S1], % where
_S1 = [b|_S1],
Ph = [b|_S1].
So there is an infinite list which certainly has not much meaning for natural language sentences (except for persons of infinite resource and capacity...).