Is there a predicate that replaces every anonymous variable, by the number 1? On a list of only zeros and ones and anonymous variables - list

I have a predicate called unify which should replace all the anonymous variables on a list (the list contains zeros, ones and anonymous variables) by the number one.
However I think I'm doing the recursion wrong, since the output isn't the list fully completed.
Here's the code:´
unify([P|T], [1|L]):-
P\==0, P\==1, !, unify(T,L).
unify([P|T],[P|L]):-
P==0; P==1,!, unify(T,L).
The output, for example, for the input unify([_,_,1,0,0,_,_],L). should be L=[1,1,1,0,0,1,1].

The name unify/2 is usually used for actual general unification. Note that this predicate is not a pure relational one.
binlist_oneified(Bs, Os) :-
must_be(list, Bs),
copy_term(Bs, Os),
term_variables(Os, Ws),
maplist(=(1), Ws).

Related

Prolog return value comparation

I'm traying to learn the basics of logic programming.
I solved some exercises, and now I'm having trouble on creating a function that take two arguments, a list of non empty lists whose elements concatenated together form the second argument.
By the time I created a function that concat the elements of a list of lists:
concat([[]|L],L3):- concat(L,L3).
concat([[Head|L1]|L2],[Head|L3]):- concat([L1|L2],L3),!.
Now, what I need to know is how to take the return value of that function and compare it with a list (the second argument of the function).
This is one approach that will allow down to single elements in a sublist, but not an empty sublist:
concat([[L]], [L]).
concat([[H],L|T], [H|R]) :- concat([L|T], R).
concat([[H1,H2|T]|LT], [H1|RT]) :- concat([[H2|T]|LT], RT).
The method here to avoid an empty list is to call out two head elements in the recursive clause, and a solitary element list in the base case. This prevents empty sublists from succeeding, as requested in the comments of the original post.
If you have a variable, Y that is already instantiated, and you want to know if it is the result of concatenating the list of lists, LL, you simply query:
concat(LL, Y).
This will be true if Y is the concatenation of list LL and false if it is not. You don't have to "return and compare" (as, for example, in C, you might say, concat(LL) == Y, or concat(LL, X); if (X == Y)...). This is because concat is a relation defined between the two arguments and it determine if the query can be made true by following the stated rules (clauses of the predicate).
If you already obtained a result and want to determine if it's unifiable to another variable, Z, then you can say:
concat(X, Y), Y = Z.
Note that, in Prolog, concat(X, Y) == Z is not correct to determine if the result of the predicate is equal to Z because it is not a function that returns a value.
Prolog doesn't have functions or return values in the sense of a procedural programming language. It has predicates, which assert a relationship. It has terms, which include variables which comes with some strictures:
All variables are local, and
A variable, once assigned a value, ceases to be variable. That's why it's called unification.
So....
If you want a predicate that will take two lists and produce their concatenation, you'll need to pass it a 3rd variable. You might invoke it like this:
concat([a,b],[c,d],X).
which asserts that X is the concatenation of [a,b] and [c,d]. Prolog's inference engine will then evaluate the truth or falseness of the assertion.
Most recursive problems has a few special cases and a more general case. The implementation of such a concat/3 predicate might look something like this (annotated to explain what it's doing).
First, we have one special (and terminating) case: If the left-hand list is empty, the concatenation is simply the right-hand list.
concat( [] , Bs , Bs ).
Next, we have the one general case: if the left-hand list is non-empty, we need to prepend it to the concatentation that we're building (and then recurse down.)
concat( [A|As] , Bs , [A|Cs] ) :-
concat(As,Bs,Cs).
That's all there is two it. You'll also notice that it's bi-directional: it's perfectly happy to split lists apart as well. Invoking it like this:
concat( Prefix , Suffix, [a,b,c,d] ).
will, on backtracking, produce all the possible ways that [a,b,c,d] could be split into a prefix and suffix:
Prefix Suffix
--------- ---------
[] [a,b,c,d]
[a] [b,c,d]
[a,b] [c,d]
[a,b,c] [d]
[a,b,c,d] []
You just need the base case
concat([],[]).
concat([[]|L],L3):- concat(L,L3).
concat([[Head|L1]|L2],[Head|L3]):- concat([L1|L2],L3).
It also works for empty (sub)lists.
I've removed the useless cut.

Prolog copy a specific letter from a list to another in the same place

so I'm trying to make a method in prolog that gets a character and 2 lists, in whatever place the character is found in list 1, I inject that character in the list 2. The method returns the new state of the list 2. It doesn't seem to work even if I find it correct. Here's my code.
transfer([],[],_,[])
transfer([H¦T],[_¦T1],C,R):-
transfer(T,T1,C,R1),
H==C,
append([H],R1,R).
So if I executed ?- transfer([h,e,l,l,o],[0,0,0,0,0],e,X). I would get as result X=[0,e,0,0,0]. Any ideas?
Just think about what relation your predicate should describe. If the first two lists are empty, the last argument is also an empty list, no matter the comparison element. This is the base case you already have. Otherwise you have two mutually exclusive cases:
The head of the first list equals the comparison element. In this case the comparison element is in the result list.
The head of the first list is different from the comparison element. In this case the head of the second list is in the result list.
You can model this case distinction with the or-predicate ;. Then transfer/4 might look something like that:
transfer([],[],_,[]).
transfer([H1|T1],[H2|T2],C,[R|Rs]):-
((H1=C,R=C);(dif(H1,C),R=H2)), % case 1 or case 2
transfer(T1,T2,C,Rs). % the relation holds for the tails as well
With this definition your example query yields the desired result:
?- transfer([h,e,l,l,o],[0,0,0,0,0],e,X).
X = [0,e,0,0,0] ? ;
no
Alternatively you could also describe the case distinction above in a separate predicate and then use maplist/4 to apply the relation to the three lists:
:- use_module(library(apply)).
e_x_y_z(E,X,Y,Z) :-
(X=E,Z=E);(dif(X,E),Z=Y).
transfer(L1,L2,C,R) :-
maplist(e_x_y_z(C),L1,L2,R).
I find this version somewhat easier to read since the definition of the actual relation is separated from the recursion. Note how the comparison element in e_x_y_z/4 is the first argument, so the predicate can be passed to maplist/4 lacking three arguments for the elements of the three lists respectively.

Prolog Insert the number in the list by the tail

How can I build a predicate in prolog that receives a number and a list, I must insert the number in the list by the tail
I tried inserting the number in the list by the head: insert(H,[P|Q],[H,P|Q]). and it works, but how can I do it by the tail?
Inserting at the tail can be done with a two-part recursive rule:
When the list is empty, unify the result to a single-element list with the item being inserted
When the list is not empty, unify the result to a head followed by the result of inserting into the tail of a tail.
English description is much longer than its Prolog equivalent:
ins_tail([], N, [N]).
ins_tail([H|T], N, [H|R]) :- ins_tail(T, N, R).
Demo.
Simply use append/3 like this:
?- append([a,b,c,d],[x],List).
List = [a,b,c,d,x].
Nobody talked about difference lists yet.
Difference lists
Difference lists are denoted L-E, which is just a convenient notation for a couple made of a list L whose last cons-cell has E for its tail:
L = [ V1, ..., Vn | E]
The empty difference list is E-E, with E a variable. You unify E whenever you want to refine the list.
For example, if you want to add an element X, you can unify as follows:
E = [X|F]
And then, L-F is the new list. Likewise, you can append lists in constant time. If you unify F with a "normal" list, in particular [], you close your open-ended list. During all operations, you retain a reference to the whole list through L. Of course, you can still add elements in front of L with the ususal [W1, ..., Wm |L]-E notation.
Whether or not you need difference lists is another question. They are intereseting if adding an element at the end is effectively a common operation for you and if you are manipulating large lists.
Definite clause grammars
DCG are a convenient way of writing grammar rules in Prolog. They are typically implemented as reader macros, translating --> forms into actual predicates. Since the purpose of grammars is to build structures during parsing (a.k.a. productions), the translation to actual predicates involves difference lists. So, even though both concepts are theoretically unrelated, difference lists are generally the building material for DCGs.
The example on wikipedia starts with:
sentence --> noun_phrase, verb_phrase.
... which gets translated as:
sentence(S1,S3) :- noun_phrase(S1,S2), verb_phrase(S2,S3).
A lot of "plumbing" is provided by the syntax (a little like monads). The object being "built" by sentence/2 is S1, which is built from different parts joined together by the predicates. S1 is passed down to noun_phrase, which builds/extends it as necessary and "returns" S2, which can be seen as "whatever extends S1". This value is passed to verb_phrase which updates it and gives S3, a.k.a. whatever extends S2. S3 is an argument of sentence, because it is also "whatever extends S1", given the rule we have. But, this is Prolog, so S1, S2 and S3 are not necessarly inputs or outputs, they are unified during the whole process, during which backtracking takes place too (you can parse ambiguous grammars). They are eventually unified with lists.
Difference lists come to play when we encounter lists on the right-hand side of the arrow:
det --> [the].
The above rule is translated as:
det([the|X], X).
That means that det/2 unifies its first argument with an open-ended list which tail is X; other rules will unify X. Generally, you find epsilon rules which are associated with [].
All the above is done with macros, and a typical error is to try to call an auxiliary predicate on your data, which fails because the transformation add two arguments (a call to helper(X) is in fact a call to helper(X,V,W)). You must enclose actual bodies between braces { ... } to avoid treating prediates as rules.

Prolog create list of lists

I'm having some (or a lot of) trouble with lists of lists in prolog.
So I have a list of numbers, say [5,6,1,3] as input.
The output should be [[5,25],[6,36],[1,1],[3,9]].
I already have a predicate that 'return's the 2 item lists (keep in mind that I'll have to change the get_squared_pair function to get some other relevant value):
get_squared_pair(Number, Result) :-
get_squared_value(Number, SquareValue),
Result = [Number, SquareValue].
get_squared_value(Number, Result) :-
Result is Number * Number.
Until here it's pretty logical. Now I need a predicate that recursively iterates though a list, adds the squared pair to a new list, and then returns this lists of lists. What I have right now is:
return_list([], 0).
return_list([Head | Tail], Result) :-
get_squared_pair(Head, Add),
append(Add,Result),
return_list(Tail, Result).
This doesn't work for a number of reasons, and it's mostly because I can't seem to figure out how the recursion actually works with lists, much less lists of lists. Also it's currently running in the wrong order which doesn't help.
I understand this might be a bit vague but I've tried googling my way out of this one but can't seem to translate what I find into my own problem very well.
Any help would be much appreciated!
Let's look at your get_squared_pair/2 first. Although it's working, it can be tidied up a bit which will also help understand how Prolog works. The primary mechanism of Prolog is unification, which is not the same as assignment which occurs in other languages. In unification, Prolog examines two terms and attempts to unify them by instantiating variables in one or both of the terms to make them match. There are some predicates in Prolog, like is/2 which are used to evaluate expressions in one argument, and then unify the first argument with that result.
Your first predicate, then, which you have written as:
get_squared_pair(Number, Result) :-
get_squared_value(Number, SquareValue),
Result = [Number, SquareValue].
get_squared_value(Number, Result) :-
Result is Number * Number.
Can be simplified in two ways. First, you can consolidate the get_squared_value/2 since it's just one line and doesn't really need its own predicate. And we'll rename the predicate so it's not imperative.
square_pair(Number, Square) :-
S is Number * Number, % Square the number
Square = [Number, S]. % Unify Square with the pair
Prolog can unify terms in the head of the clause, so you can avoid the redundant unification. So this is all you need:
square_pair(Number, [Number, Square]) :-
Square is Number * Number.
On to the main predicate, return_list/2. First, we'll rename this predicate to square_pairs. When doing recursion with lists, the most common pattern is to continue reducing a list until it is empty, and then a base case handles the empty list. Your implementation does this, but the base case is a little confused since the 2nd argument is an integer rather than a list:
square_pairs([], 0).
This really should be:
square_pairs([], []).
Your main predicate clause isn't making correct use of append/2. There are two forms of append in SWI Prolog: append/2 and append/3. You can look up what these do in the SWI Prolog online documentation. I can tell you that, in Prolog, you cannot change the value of a variable within a predicate clause once it's been instantiated except through backtracking. For example, look at the following sequence that might be in a predicate clause:
X = a, % Unify X with the atom 'a'
X = b, % Unify X with the atom 'b'
In this case, the second expression will always fail because X is already unified and cannot be unified again. However, if I have this:
foo(X), % Call foo, which unifies X with a value that makes 'foo' succeed
bar(X, Y), % Call bar, which might fail based upon the value of 'X'
In the above case, if bar(X, Y) fails, then Prolog will backtrack to the foo(X) call and seek another value of X which makes foo(X) succeed. If it finds one, then it will call bar(X, Y) again with the new value of X, and so on.
So append(Add, Result) does not append Add to Result yielding a new value for Result. In fact, append with two arguments says that the second list argument is the concatenation of all the elements of the first list, assuming the first argument is a list of lists, so the definition of append/2 doesn't match anyway.
When thinking about your recursion, realize that the argument lists are in one-to-one correspondence with each other. The head of the result list is the "square pair" for the head of the list in the first argument. Then, recursively, the tail of the 2nd argument is a list of the square pairs for the tail of the first argument. You just need to express that in Prolog. We can also use the technique I described above for unification within the head of the clause.
square_pairs([Head | Tail], [SqPair | SqTail]) :-
square_pair(Head, SqPair),
square_pairs(Tail, SqTail).
square_pairs([], []).
Now there's another simplification we can do, which is eliminate the square_pair/2 auxiliary predicate completely:
square_pairs([Head | Tail], [[Head, SqHead] | SqTail]) :-
SqHead is Head * Head,
square_pairs(Tail, SqTail).
square_pairs([], []).
There's a handy predicate in Prolog called maplist which can be used for defining a relationship which runs parallel between two lists, which is the scenario we have here. We can bring back the square_pair/2 predicate and use maplist:
square_pairs(Numbers, SquarePairs) :-
maplist(square_pair, Numbers, SquarePairs).
So you want to turn your list into another, such that each element (a number) is turned into a two-element list, the number and its square.
All you need to do is to tell that to Prolog. First, the second one:
turn_into_two(Num, [A,B]):-
what is A?
A is Num,
what is B? We just tell it to Prolog, too:
B is ... * ... .
Now, on to our list. A list [A|B] in Prolog consists of its head element A, and its tail B - unless it's an empty list [] of course. It doesn't matter what the list's elements are; a list is a list.
We need to account for all cases, or else we're not talking about lists but something else:
turn_list([], Res):-
so what is our result in case the list was empty? It should be empty as well, right?
Res = ... .
in the other case,
turn_list([A|B], Res):-
our result won't be empty, so it'll have its head and tail, correct?
Res = [C|D],
next we say what we know about the heads: the input list's head turns into that two elements list we've described above, right?
turn_into_two(A,C),
and then we say our piece about the tails. But what do we know about the tails? We know that one is the result of the conversion of the other, just as the whole list is:
turn_list( ... , ...) .
And that's it. Incidentally, what we've described, follows the paradigm of mapping. We could have used any other predicate in place of turn_into_two/2, and it would get called for each of the elements of the input list together with the corresponding element from the resulting list.

Prolog computing type of tuples

For an assignment, I have to create a type inference relation. here's the approach I used
tuples([]).
tuples(_|_).
type(tuples([]),tuples([])).
type(tuples(X|T),tuples(Y|Z)) :- type(tuples(T),tuples(Z)),type(X,Y).
I have already defined the type relation for all possible terms required for my assignment where y is the type of X in type(X,Y). For defining types of n-tuples, I used the approach similiar to the one used for appending lists.
But prolog always returns false when I ask
?-type(tuples([3,str]),Z)
or even
?-type(tuples([3,str]),tuples(Z))
or
?-type(tuples([3,str,4,abc,5,6]),Z)
i.e a list of length n, the answer returned is false.
Nothing changed even when I revered the sub-rules in the last rule.
tuples([]).
tuples(_|_).
type(tuples([]),tuples([])).
type(tuples(X|T),tuples(Y|Z)) :- type(X,Y),type(tuples(T),tuples(Z)).
I am not asking for alternative approaches to type of tuples to help me in my assignment but I can't figure out why this approach is not working.
It looks like your definition of a tuple is a List with length 2.
This rule does not check for that:
tuples(_|_).
What you probably want is this:
tuples([_,_]).
If you want it to check for any length list, use:
tuples([_|_]).
In the latter rule, the first wildcard represents the first item in the list (the head) and the second wildcard represents the rest of the list (the tail).

Resources