List-Comprehension in Erlang - Variable unbound in guard - filter

I am trying to build a list recursively with this method. OL (occurence list of characters) is a list that will eventually shrink to []. I need to use Q in the guard to check if the item can be subtracted. Basically it shall produce a filtered cartesian product.
b([[]], _)->[[]];
b(_, [])-> [[]];
b(OL, Keys)->[Y++[Q] || Y <- b(subtract(Q,OL), Keys), Q <-Keys, len(subtract(Q,OL)) < len(OL)].
But i get the error:
variable 'Q' is unbound
Is there any way to use its value at that place?
The subtract-method filters characters out of another list.
subtract([{$a,1}],[{$a, 5},{$b, 1}]) returns [{$a, 5},{$b, 1}].
len() sums up the integer values of each tuple.
len([{$a, 5},{$b, 1}]) returns 6.

Try to put Q generator before its usage in Y generator. I guess the definitions are applied from left to right so when Y is applied there is no Q defined.

Related

How to correct this 'Greater Than' Arithmetic Prolog code?

I am trying to write a simple prolog program where a number is compared with the elements in a list. To check that the number is greater than which elements in the list, and it simply returns the list with the elements that are less than the number. Example: gt(12,[19,4,6,22],L), this should return L = [4,6].
Here is my attempt:
gt(_,[],[]):-!.
gt(Num,[H|T],[H|L]):-
Num>H,
gt(Num,T,L).
gt(Num,[H|T],[H|L]):-
Num=<H,!,
gt(Num,T,L).
The problem that I am facing is in the =< predicate. If the condition is =< the number, then I am trying to say that ignore and move to the next number gt(Num,T,L). The place where I have written L, what should I write here so that it understands that I don't want you to write that value in the list?
Works alright for values that are already smaller than the number.
?-gt(12,[6,7,6],L).
L = [6,7,6]
But fail for such tests:
?- gt(12,[19,6,7],L).
L = [19, 6, 7]
The problem is in the third parameter in the third clause of gt/3. It is also "adding" the current item H as the head of the output list.
You should write
gt(Num,[H|T],L):-
Num=<H,!,
gt(Num,T,L).
instead.
You may also get rid of those cuts (!) to make your procedure work with other modes for the parameters and/or with uninstantiated variables.

Every possible combination of logic for tree - Algorithm?

The letters represent a true/false value
True allows the traversal of the lower levels; false means the lower letters will all be false too.
For example, if a is false, all the letters beneath will also be false.
Given any formation of tree, always with 3 levels, how do I calculate all the valid combinations of true/false values for the all letters?
Im looking for names of algorithms, links to resources. Not how you would implement it.
Thanks, any help appreciated.
There is a simple recursive algorithm. The following results in enumerations of sets of letters assigned T; since letters are assigned either T or F, it's obvious how to derive the complete mapping:
# I use ++ for the operation of concatenating lists/sets
# and [X] to produce a list/set consisting of the single element X
enumerate(Q, Accum):
if Q is empty:
return [Accum]
else:
remove the head of Q and put it in Head
return enumerate(Q, Accum) ++
enumerate(children(Head) ++ Q, Accum ++ [Head])
To enumerate the combinations of a forest, call
enumerate(Roots(Forest), [])

how to assign one list to a variable in prolog?

I want to append([],C,C) where C is a list containing some elements . Is it possible? I will append some list in C containing elements append (Found,C,C) if other condition is true.
And also i want to store final value in C to a variable D . How can I do that?
I want to append([],C,C) where C is a list containing some elements. Is it possible?
append([],C,C) is always true. An empty list combined with anything is that anything. Look what Prolog says when you attempt it:
?- append([],C,C).
true.
This true without any bindings tells you that Prolog established the proof but no new bindings were created as a result. This code would have the same result:
meaningless(_, _, _).
?- meaningless(everybody, X, Squant).
true.
This suggests your desire is misplaced. append([], C, C) does not do what you think it does.
I will append some list in C containing elements append (Found,C,C) if other condition is true. And also i want to store final value in C to a variable D. How can I do that?
Thinking in terms of "storing" and other operations implying mutable state is a sure sign that you are not understanding Prolog. In Prolog, you establish bindings (or assert facts into the dynamic store, which is a tar pit for beginners). Something similar could be achieved in a Prolog fashion by doing something like this:
frob(cat, List, Result) :- append([cat], List, Result).
frob(dog, List, List).
This predicate frob/3 has two in-parameters: an atom and a list. If the atom is cat then it will append [cat] to the beginning of the list. The threading you see going between the arguments in the head of the clause and their use in the body of the clause is how Prolog manages state. Basically, all state in Prolog is either in the call stack or in the dynamic store.
To give an example in Python, consider these two ways of implementing factorial:
def fac(n):
result = 1
while n > 1:
result = result * n
n = n - 1
This version has a variable, result, which is a kind of state. We mutate the state repeatedly in a loop to achieve the calculation. While the factorial function may be defined as fac(n) = n * fac(n-1), this implementation does not have fac(n-1) hiding in the code anywhere explicitly.
A recursive method would be:
def fac(n):
if n < 1:
return 1
else:
return n * fac(n-1)
There's no explicit state here, so how does the calculation work? The state is implicit, it's being carried on the stack. Procedural programmers tend to raise a skeptical eyebrow at recursion, but in Prolog, there is no such thing as an assignable so the first method cannot be used.
Back to frob/3, the condition is implicit on the first argument. The behavior is different in the body because in the first body, the third argument will be bound to the third argument of the append/3 call, which will unify with the list of the atom cat appended to the second argument List. In the second body, nothing special will happen and the third argument will be bound to the same value as the second argument. So if you were to call frob(Animal, List, Result), Result will be bound with cat at the front or not based on what Animal is.
Do not get mixed up and think that Prolog is just treating the last argument as a return value! If that were true, this would certainly not work like so:
?- frob(X, Y, [whale]).
X = dog,
Y = [whale].
What appears to have happened here is that Prolog could tell that because the list did not start with cat it was able to infer that X was dog. Good Prolog programmers aspire to maintain that illusion in their APIs, but all that really happened here is that Prolog entered the first rule, which expanded to append([cat], X, [whale]) and then unification failed because Prolog could not come up with an X which, having had [cat] prepended to it, would generate [whale]. As a result, it went to the second rule, which unifies X with dog and the second two arguments with each other. Hence Y = [whale].
I hope this helps!

Understand Arguments in Prolog

This may be a stupid question but at Uni we were presented with a Prolog segment that multiplies arrays. It has 4 predicates of which one I cannot understand what it does or how to execute it. Can you give me any hint or explanation?
multiply([],_,[]).
multiply([V0|Rest], V1, [Result|Others]):-
multiply(Rest,V1,Others),
inner_product(V0,V1,Result).
I tried to run the predicate like this:
multiply([1,2],3,X).
multiply([[1,2]],[3],X).
multiply([[1,2]],3,X)
multiply([1,2],[3,2],X).
but everything returned false.
Is there anything I am doing wrong?
No information has been given about what kind of arguments are expected, but you can determine it by looking at the clauses for multiply:
multiply([],_,[]).
This indicates that the first and third arguments are lists, of some kind.
multiply([V0|Rest], V1, [Result|Others]):-
multiply(Rest,V1,Others),
inner_product(V0,V1,Result).
inner_product, though not defined as #CapelliC pointed out, indicates that V0 and V1 are vectors (or in prolog, lists of scalar quantities) of the same length by definition of an inner product. And the Result value will be a scalar.
So, for multiply(M1, V, Result). to succeed:
M1 must be a list of lists, or a matrix. Each inner list must be the same length and it must be a list of scalar values
V must be a list of scalar values, and of the same length as the inner lists of M1
Inferred by the recursion, Result will be a vector (a list) of scalar values and the list will have a length equal to the length of M1 (have the same number of scalars as M1 has vectors).
In other words, it's following the rules of standard matrix/vector multiplication.
Looking at all the test cases shown, they will all fail because none of them match all 3 criteria above.
multiply([1,2],3,X). % Fails item #1 above
% `3` isn't a vector/list
multiply([[1,2]],[3],X). % Fails item #2 above
% length of [3] isn't length of [1,2]
multiply([[1,2]],3,X) % Fails item #2 above
% `3` isn't a vector/list
multiply([1,2],[3,2],X). % Fails item #1 above
% `[1,2]` isn't a list of lists (matrix)
So they will all fail just on the basis of not matching the expected configuration of arguments that allow the predicate to succeed.
Try something like:
multiply([[1,2,3],[3,2,1]], [1,1,1], X).
You should get:
X = [6,6]

Counting the number of lists in a nested list

I am having troubles counting the number of lists in a nested list.
count_lists([H|T],R):-
atomic(H),!,
count_lists(T,NR),
R is NR+1.
count_lists([[H|T]|Rest],R):-
!,
count_lists([H|T],R1),
count_lists(Rest,R2),
R is R1+R2.
count_lists([],0).
First of all, I try the basic case where an element in the list is atomic and thus, I should increment the counter by one. (Also, I tried removing the atomic predicate because I figured that because of it, my code will compute the number of elements in a nested list, but it still doesn't work)
Then, if the first element is a list itself, I go recursively on it and on the remaining list, adding the results.
And the third clause is states that the number of nested lists in an empty list is 0.
?count_lists([[1,5,2,4],[1,[4,2],[5]],[4,[7]],8,[11]],R).
should return 8 but instead, returns 12.
I know it's been a while since you asked this, but here is the answer I think you were looking for:
count_lists([],1).
count_lists([H|T],Rez):-atomic(H),!,count_lists(T,Part),Rez is Part.
count_lists([H|T],Rez):-count_lists(H,Part1),count_lists(T,Part2),Rez is Part1+Part2.
This way, you count only the number of lists and not the number of elements within.
you need to distinguish lists from other elements, i.e.
count_lists(E,R):-
is_list(E),!,count_elems(E,N),
R is N+1.
count_lists(_,0).
count_elems([H|T],R):-
count_lists(H,Hc),
count_elems(T,Tc),
R is Hc+Tc.
count_elems([],0).
but the code is contrived, using library we can get it done in 1 step:
count_lists(E, R):-
maplist(count_lists, E, Cs) -> sum_list(Cs, S), R is S+1 ; R = 0.
the code can be understood only WRT maplist/N behaviour
?- maplist(_,a).
false.
?- maplist(_,[]).
true.
?- maplist(_,[1]).
ERROR: apply:maplist_/2: Arguments are not sufficiently instantiated
In your solution you forget that e.g. [1,2,3] = [1,2,3| []] or [1,2,3] = [1| [2| [3| []]]]. Thus, you're "over-counting", thanks to your first clause. For example:
?- count_lists([1,2,3], N).
N = 3.
But there's another problem. In your second clause, if you've a nested list that nests other lists, you don't count it. Not clear from the title if that's intended or if it's a bug.
You shouldn't have complicated yourself.
count([],1).
count([L1|L2],Rez):- count(L1,Rez1),count(L2,Rez2),Rez is Rez1+Rez2.
You take out all the elements in a list recursively until you are left out with the empty list which values 1.

Resources