Associative list in Prolog - list

i m doing associative list in prolog
i seen this topic but i dont understand the code.
Associative Lists in Prolog
For checking list is associative isn't enough do this:
lists([_X, _Y]).
lists([[H|_T]|L],[H|T]):- lists(L,T).
Because for first /1 i check if have element in this way [a,3]
and /2 take list of list [[a,4],[a,3]] in this way.
so first pass call list/2 on [a,3], and check true for base case, and after call [a,4] and call true for base case too.
I wrong something, but i don't see,
Anyone can clarify me?
OP's update of 2019-01-01 10:40:47Z:
I try to resolve in this way:
islist([_X,_Y]).
islist([_X|T]):- islist(T).
In this case accept just input in this way
[[k,v],[k,v],[k,v]]
but accept all input like this:
[a]
[k,v,v,v]
[[k,v],[k,v],[k,v,v]]
So my problem remains.

From the linked question:
"[] is the list ; [also, if] k is a key, v is a value and a is an
associative list, then [[k, v] | a] is an associative list."
Just write this down in Prolog:
associative_list(L) :- L = [].
associative_list(L) :- K=K, V=V, associative_list(A), L = [[K, V] | A].
Of course Prolog as a programming language has operational concerns as well as its logical semantics, so the last line is better written instead as
associative_list(L) :- L = [[_K, _V] | A], associative_list(A).
An idiomatic way to write this is
associative_list([]).
associative_list([[_, _] | A]) :- associative_list(A).

Related

SWI-Prolog: How to stop the predicate when the list is empty? (predicate included)

course(cmput325).
course(cmput175).
course(cmput201).
course(cmput204).
prerequisite(cmput204, cmput325).
prerequisite(cmput175, cmput201).
prerequisite(cmput175, cmput204).
I need to write a new predicate, which is
can_take(+L,?C).
Definition:
L is a given list of courses that a student has already taken. If C is also given,then the predicate should check whether the student has all the required courses for C. If C is a variable, then with backtracking, the predicate should produce one course at a time that the student can take now. Courses can be in any order, but each course should be generated only once, and you should not return any courses that the student has already taken.
Example:
?- findall(C, can_take([cmput175], C), L).
should return
L = [cmput201, cmput204].
Here is my predicate:
can_take(L,C) :- prerequisite(L,C).
can_take([L|List],C) :- prerequisite(L,C),can_take(List,C).
This predicate didn't return the correct result, and it just returned false. I think it is because I didn't determine the condition when L is empty, however, if I tried to add L \== [] in either of them. It still gave me error...what should I do so that this predicate will stop and give me result?
-------update-------
pre(X,C) :- prerequisite(X,C).
pre(X,C) :- prerequisite(X,Y), pre(Y,C).
pre2(C,L) :- findall(L1,pre(L1,C),L).
required(C,L) :- pre2(C,L1),sort(L1,L).
can_take([],_).
can_take(L,C) :- required(C,L).
can_take([L|List],C) :- prerequisite(L,C),can_take(List,C).
Here is my code test:
?- required(cmput325,L).
L = [cmput175, cmput204].
?- required(cmput204,L).
L = [cmput175].
?- can_take([cmput175],X).
X = cmput201 ;
X = cmput204 ;
?- findall(C, can_take([cmput175], C), L).
L = [cmput201, cmput204].
?- can_take([cmput204],cmput325).
false. (this one is OK)
?- can_take([cmput175,cmput204],cmput325).
true ;
false. (this one is OK)
?- can_take([cmput175],cmput204).
true ;
true ;
false.
the last one is not ok because I don't want it to return two true statements...so what I want is just let it stop when either second or last line returns true. For my assignment, I am not allowed to use cut operator !, is there any other way to do it?
(I will assume that you can take a course a second time, even if you have taken it already. That at least are the rules I know of.)
You can take a course, provided you have taken all required courses already.
There is no direct "all" in Prolog. But you can formulate this differently
You can take a course, provided there is no required course that you have not taken already.
can_take(Takens, Next) :-
course(Next),
iwhen( ground(Takens),
\+ ( prerequisite(Required, Next), \+ member(Required, Takens) ) ).
This uses iwhen/2 to guard against cases where Takens is not fully instantiated.
Note that there is a slight difference to your examples:
?- findall(C, can_take([cmput175], C), L).
L = [cmput175, cmput201, cmput204].
% ^^^^^^^^
Disclaimer
Your problem is inherently non-monotonic: By adding further facts for requirements you are reducing the number of possible courses you may take. As a beginner, rather stick to problems that are monotonic in nature. It is on this side where Prolog really excels.

Understanding Prolog's empty lists

I am reading Bratko's Prolog: Programming for Artificial Intelligence. The easiest way for me to understand lists is visualising them as binary trees, which goes well. However, I am confused about the empty list []. It seems to me that it has two meanings.
When part of a list or enumeration, it is seen as an actual (empty) list element (because somewhere in the tree it is part of some Head), e.g. [a, []]
When it is the only item inside a Tail, it isn’t an element it literally is nothing, e.g. [a|[]]
My issue is that I do not see the logic behind 2. Why is it required for lists to have this possible ‘nothingness’ as a final tail? Simply because the trees have to be binary? Or is there another reason? (In other words, why is [] counted as an element in 1. but it isn't when it is in a Tail in 2?) Also, are there cases where the final (rightmost, deepest) final node of a tree is not ‘nothing’?
In other words, why is [] counted as an element in 1. but it isn't when it is in a Tail in 2?
Those are two different things. Lists in Prolog are (degenerate) binary trees, but also very much like a singly linked list in a language that has pointers, say C.
In C, you would have a struct with two members: the value, and a pointer to the next list element. Importantly, when the pointer to next points to a sentinel, this is the end of the list.
In Prolog, you have a functor with arity 2: ./2 that holds the value in the first argument, and the rest of the list in the second:
.(a, Rest)
The sentinel for a list in Prolog is the special []. This is not a list, it is the empty list! Traditionally, it is an atom, or a functor with arity 0, if you wish.
In your question:
[a, []] is actually .(a, .([], []))
[a|[]] is actually .(a, [])
which is why:
?- length([a,[]], N).
N = 2.
This is now a list with two elements, the first element is a, the second element is the empty list [].
?- [a|[]] = [a].
true.
This is a list with a single element, a. The [] at the tail just closes the list.
Question: what kind of list is .([], [])?
Also, are there cases where the final (rightmost, deepest) final node of a tree is not ‘nothing’?
Yes, you can leave a free variable there; then, you have a "hole" at the end of the list that you can fill later. Like this:
?- A = [a, a|Tail], % partial list with two 'a's and the Tail
B = [b,b], % proper list
Tail = B. % the tail of A is now B
A = [a, a, b, b], % we appended A and B without traversing A
Tail = B, B = [b, b].
You can also make circular lists, for example, a list with infinitely many x in it would be:
?- Xs = [x|Xs].
Xs = [x|Xs].
Is this useful? I don't know for sure. You could for example get a list that repeats a, b, c with a length of 7 like this:
?- ABCs = [a,b,c|ABCs], % a list that repeats "a, b, c" forever
length(L, 7), % a proper list of length 7
append(L, _, ABCs). % L is the first 7 elements of ABCs
ABCs = [a, b, c|ABCs],
L = [a, b, c, a, b, c, a].
In R at least many functions "recycle" shorter vectors, so this might be a valid use case.
See this answer for a discussion on difference lists, which is what A and Rest from the last example are usually called.
See this answer for implementation of a queue using difference lists.
Your confusion comes from the fact that lists are printed (and read) according to a special human-friendly format. Thus:
[a, b, c, d]
... is syntactic sugar for .(a, .(b, .(c, .(d, [])))).
The . predicate represents two values: the item stored in a list and a sublist. When [] is present in the data argument, it is printed as data.
In other words, this:
[[], []]
... is syntactic sugar for .([], .([], [])).
The last [] is not printed because in that context it does not need to. It is only used to mark the end of current list. Other [] are lists stored in the main list.
I understand that but I don't quite get why there is such a need for that final empty list.
The final empty list is a convention. It could be written empty or nil (like Lisp), but in Prolog this is denoted by the [] atom.
Note that in prolog, you can leave the sublist part uninstantiated, like in:
[a | T]
which is the same as:
.(a, T)
Those are known as difference lists.
Your understanding of 1. and 2. is correct -- where by "nothing" you mean, element-wise. Yes, an empty list has nothing (i.e. no elements) inside it.
The logic behind having a special sentinel value SENTINEL = [] to mark the end of a cons-cells chain, as in [1,2,3] = [1,2|[3]] = [1,2,3|SENTINEL] = .(1,.(2,.(3,SENTINEL))), as opposed to some ad-hoc encoding, like .(1,.(2,3)) = [1,2|3], is types consistency. We want the first field of a cons cell (or, in Prolog, the first argument of a . functored term) to always be treated as "a list's element", and the second -- as "a list". That's why [] in [1, []] counts as a list's element (as it appears as a 1st argument of a .-functored compound term), while the [] in [1 | []] does not (as it appears as a 2nd argument of such term).
Yes, the trees have to be binary -- i.e. the functor . as used to encode lists is binary -- and so what should we put there in the final node's tail field, that would signal to us that it is in fact the final node of the chain? It must be something, consistent and easily testable. And it must also represent the empty list, []. So it's only logical to use the representation of an empty list to represent the empty tail of a list.
And yes, having a non-[] final "tail" is perfectly valid, like in [1,2|3], which is a perfectly valid Prolog term -- it just isn't a representation of a list {1 2 3}, as understood by the rest of Prolog's built-ins.

Prolog- Mappings (Associative Arrays)

I am studying prolog and was wondering if anybody give me guidance on how to go about doing this question, It's the first of many in this area and knowing how to do this question will really help me progress. Thank-you in advance.
Using Prolog define a predicate mapof(K, M, V) such that, when invoked with K instantiated to a key, and M instantiated to a mapping, mapof will instantiate the variable V to the value (or one of the values) associated with K in mapping M. The predicate should fail if K does not appear as a key in mapping M.
It really depends how you want to represent your "mapping". In Prolog, a table of facts is the most obvious approach. For two mappings m and n:
m(a, 1).
m(b, 2).
m(c, 3). % and so on
n(a, foo).
n(b, bar).
n(c, baz). % and so on
Then, your mapof would be something along the lines of:
mapof(K, m, V) :- m(K, V).
mapof(K, n, V) :- n(K, V).
or maybe:
mapof(K, M, V) :- call(M, K, V).
A list can be used to represent a mapping, as shown by #Yasel, but a list [a, b, c] in Prolog is a nested term like .(a, .(b, .(c, []))). You don't usually represent an associative array as a singly linked list, right?
In SWI-Prolog there is a library that is better than using a simple list for a backtrackable associative array represented as a Prolog term: library(assoc). With it, you can do:
mapof(K, M, V) :- gen_assoc(K, M, V).
This library represents the associative array as an AVL tree. You can find in the SWI-Prolog code source two more associative array implementations: one using RB-trees, and one that uses non-backtrackable RB-trees.
All three libraries mentioned here are probably more efficient than a simple list of key-value pairs [k1-v1, k2-v2...] if your associative array has more than say around 100 key-value pairs in it. This doesn't mean that using a list of pairs and doing member(Key-Value, List_of_pairs) is wrong; it is the cheapest solution for simple cases.
Using the built-in predicate member/2 you can build your predicate mapof/3 like this:
mapof(K, M, V):- member((K,V), M).
Consult:
?- mapof(k1, [(k, a),(k1,b),(k2,c),(k1,d)], V).
V = b ;
V = d.

Element handling issue in Prolog, but not in a regular list?

I'm trying to write an element handling function in Prolog. It's almost the same as the prolog predicate member/2 but it must do the job in a different way. For being specific; I must say the member/2 predicate function is this:
member(X, [X|_]).
member(X, [_|Tail]) :-
member(X,Tail).
When you give a query for example: member(X, [1,2,3]).
It gives you X = 1; X = 2; X = 3; in this order for all redo's. I want an element function almost the same. I want the same result with the member function when I give a query like this:
element(X, (1,2,3)).
The difference is just parenthesis instead of bracekts like these : []
In order to do this I tried that:
element(X, (X,_)).
element(X, (_,Tail)) :-
element(X,Tail).
Which is exactly the same as member/2 predicate function implementation. But this doesn't work because it doesn't giving the last element which is X=3.
So I added one more fact that is:
element(X, X).
But this doesn't work either because (obviously) it is giving unnecessary answer with real elements like these:
X=(1,2,3)
X=(2,3)
How can I handle this?
Seems that a cut can solve your problem:
element(X, (X, _)).
element(X, (_, Tail)) :-
!, element(X, Tail).
element(X, X).
test:
?- element(X, (1,2,3)).
X = 1 ;
X = 2 ;
X = 3.
?- element(2, (1,2,3,2)).
true ;
true.
Terms like (1,2,3) in Prolog have commas as their primary functor. Probably you want to use operator univ, denoted by infix =.., or its close relations functor/3 and arg/3 to pick apart these tuples.

flatten list by replacing comma with plus operator inside a list in prolog

I am working on a scenario in Prolog (eclipse) wherein I need a list structure to be reformatted.
I have a list of the form:
MyList = [a,b,c].
I was trying to see if I can flatten the list to a single element with all the commas replaced with the + operator.
So my result list would look like:
ResultList = [a+b+c]
which is a single element list. The length of the initial list is arbitrary.
I know prolog is not suited for such operations, but can this be done?
here it is, in standard Prolog. I think there should be no difference with Eclipse:
list_to_op([X,Y|T], [R]) :-
list_to_op(T, X+Y, R).
edit: bug noted by false
list_to_op([X], [X]).
list_to_op([X], R, R+X).
list_to_op([X|T], R, Q) :-
list_to_op(T, R+X, Q).
test:
?- list_to_op([a,b,c],X).
X = [a+b+c] .
The accumulator is required to give the appropriate associativity: the simpler and more intuitive definition
list_to_op1([X], X).
list_to_op1([X|R], X+T) :-
list_to_op1(R, T).
gives
?- list_to_op1([a,b,c],X).
X = a+ (b+c) .
If evaluation order is important, use list_to_op.
edit:
there is a bug: list_to_op([a,b],X) fails.
here the correction, as often happens, it's a simplification:
list_to_op([], R, R).
list_to_op([X|T], R, Q) :-
list_to_op(T, R+X, Q).
This may help
flatten_list(A,[B]) :- flatten_list_inner(A,B).
flatten_list_inner([A],A).
flatten_list_inner([H|T],H+Y) :- flatten_list_inner(T,Y).
The output is slightly different from what you wanted. It is currently [a + (b + c)]
How about this non-recursive version..
list_to_op(L, Res) :-
concat_atom(L, '+', Atom),
Res = [Atom].
?- list_to_op([a,b,c], X).
X = ['a+b+c'].
Edit: This works in Swi-prolog.. not sure about Eclipse.