Check if list is made up by bytes only - Prolog - prolog

I need to write a predicate that checks if the list is made up only by binary digits:
%Define a binary digit type
bind(0).
bind(1).
%Predicate
byte_list([]).
byte_list([X]):-
bind(X).

If you want the version with the keyword bind:
byte_list([]).
byte_list([bind(H)|T]):- bind(H), byte_list(T).
Input example:
% False
byte_list([bind(0), bind(2)]).
% True
byte_list([bind(0), bind(1)]).
If you just want to check that the values belongs to bind:
byte_list([]).
byte_list([H|T]):- bind(H), byte_list(T).
Input example:
% False
byte_list(0, 2]).
% True
byte_list([0, 1]).

With a grammar rule which describes a bit_list (bits, binary digits) as either an empty list, or a list element 0 or 1 which is followed by a bit_list.
bit_list --> [].
bit_list --> ([0] | [1]), bit_list.
e.g.
?- phrase(bit_list, [1,0,0,1,0]).
true
?- phrase(bit_list, [1,0,0,'',0]).
false
This can also generate bit lists:
?- length(Ls, 3), phrase(bit_list, Ls).
Ls = [0, 0, 0] ;
Ls = [0, 0, 1] ;
Ls = [0, 1, 0] ;
Ls = [0, 1, 1] ;
Ls = [1, 0, 0] ;
Ls = [1, 0, 1] ;
Ls = [1, 1, 0] ;
Ls = [1, 1, 1]

Related

Define a DCG in Prolog for bit strings practice problem

Before our Prolog final exam soon, I got some practice questions and I am stuck on one:
For each integer n > 0,
let Ln := {s āˆˆ {0, 1}+ | s ends in a string from 1(0 + 1)nāˆ’1}
be the set of bit-strings whose n-th to the last bit is 1. That is, Ln is described by the regular expression (0 + 1)āˆ—1(0 + 1)nāˆ’1.
Define a DCG for the 3-ary predicate s/3 such that s(n,s,[]) is true exactly if s encodes a string in Ln.
I tried for a while to get this, but I am unsure what to do, does anyone have a solution?
Here's a DCG for (0 + 1)*:
zero_or_one -->
[0].
zero_or_one -->
[1].
many_zero_or_one -->
[].
many_zero_or_one -->
zero_or_one,
many_zero_or_one.
Let's try to make it look like the regular expression you showed, just for funzies. I will not define operators and instead "parse" the regex to something that Prolog can read without new operator definitions (I am not even sure if you can make it work just with redefining operators, maybe it isn't possible). So I will define a +//2 for "or" and *//1 for "0 or more repetitions" and n//2 for "n repetitions".
+(A, B) --> [A] | [B].
*(P) --> [] | call(P), *(P).
n(P, N) --> { length(L, N) }, n_1(L, P).
n_1([], _) --> [].
n_1([_|L], P) --> call(P), n_1(L, P).
With those available I can write a query that roughly resembles your problem statement:
?- length(L, _), phrase(( *(+(0,1)), [1], n(+(0,1), 1) ), L).
L = [1, 0] ;
L = [1, 1] ;
L = [0, 1, 0] ;
L = [0, 1, 1] ;
L = [1, 1, 0] ;
L = [1, 1, 1] ;
L = [0, 0, 1, 0] ;
L = [0, 0, 1, 1] ;
L = [0, 1, 1, 0] . % it goes on
Note that here I set the n to be equal to 2, so in n//2 I am using 2 - 1 = 1.
EDIT: I noticed that the *//1 I defined is just a special case of n//2. So you can actually do this:
?- phrase(n(+(0,1), N), L).
N = 0,
L = [] ;
N = 1,
L = [0] ;
N = 1,
L = [1] ;
N = 2,
L = [0, 0] ;
N = 2,
L = [0, 1] ;
N = 2,
L = [1, 0] ;
N = 2,
L = [1, 1] ;
N = 3,
L = [0, 0, 0] .
In other words, you can leave the N argument a free variable and you will get strings of increasing length, with the length in N.

Next predicate confusion

I'm in the process of learning prolog, I'm currently writing a next predicate for a game which is really simple.
you have a list [1,0,1,0,0,1] A legal move is move a 1 to a zero position, the 1 can only move right to the first position containing 0, but it is allowed to jump over other values if necessary.
firstly I wrote a predicate to change the value 0 to 1:
flip_first_zero([0|Tail], [1|Tail]).
simple enough, now I'm trying to find the legal moves, I will try to explain my thought process:
next([],[],[]).
next([Head|Tail], Rest, Out):-
flip_first_zero([Head|Tail],List1),
append(Rest,List1,Out).
next([Head|Tail], [Head|Rest], List):-
next(Tail,Rest, List).
an example [1,0,0,1,1,1,0] the output should be [0,1,0,1,1,1,0] ; [1,0,0,0,1,1,1]; [1,0,0,1,0,1,1] ; [1,0,0,1,1,0,1].
[1,0,0,1,1,1,0] -> [0,1,0,1,1,1,0]
[1,0,0,1,1,1,0] -> [1,0,0,0,1,1,1]
[1,0,0,1,1,1,0] -> [1,0,0,1,0,1,1]
[1,0,0,1,1,1,0] -> [1,0,0,1,1,0,1]
So how I've understood this is, I loop through removing the head each time by conserving this in Rest so I can append it back on after.
Am I approaching this wrong?
The problem has two pieces: (1) the location of a 1, (2) the location of the first 0 after finding the 1 so that the 1 can be placed in its new position. The Prolog solution will reflect this. Your initial attempt tries to handle everything in a single predicate, which I believe makes the task a little more difficult.
The base case is easy. It represents the smallest valid move.
move([1,0], [0,1]).
Then the recursive cases. These enforce at least 3 positions in the list since the trivial case of 2 positions is already handled by the base case, and it establishes mutual exclusion in the rules to avoid redundant solutions.
% If we're at a 0 (space), keep going
move([0,X1,X2|T], [0|R]) :-
move([X1,X2|T], R).
% If we see a 1, we can move it, or we can leave it alone and move on
move([1,X1,X2|T], [0|R]) :-
place([X1,X2|T], R).
move([1,X1,X2|T], [1|R]) :-
move([X1,X2|T], R).
% Place the 1 at the first located 0 (space)
place([0|T], [1|T]).
place([1|T], [1|R]) :-
place(T, R).
So to determine valid next positions from a starting position:
| ?- move([1,0,0,1,1,1,0],R).
R = [0,1,0,1,1,1,0] ? a
R = [1,0,0,0,1,1,1]
R = [1,0,0,1,0,1,1]
R = [1,0,0,1,1,0,1]
(1 ms) no
| ?-
You can also determine what starting positions would lead to a particular next position:
| ?- move(S, [1,0,0,1,0,1,1]).
S = [1,0,0,1,1,0,1] ? a
S = [1,0,0,1,1,1,0]
S = [1,0,1,0,0,1,1]
no
This can also be done using a DCG:
move([0, 1]) --> [1, 0].
move([0|R]) --> see(0), move(R).
move([0|R]) --> see(1), place(R).
move([1|R]) --> see(1), move(R).
see(N), [X1, X2] --> [N, X1, X2].
place([1|T]) --> [0], seq(T).
place([1|R]) --> [1], place(R).
seq([]) --> [].
seq([X|Xs]) --> [X], seq(Xs).
| ?- phrase(move(R), [1,0,0,1,1,1,0]).
R = [0,1,0,1,1,1,0] ? a
R = [1,0,0,0,1,1,1]
R = [1,0,0,1,0,1,1]
R = [1,0,0,1,1,0,1]
no
| ?- phrase(move([1,0,0,1,0,1,1]), S).
S = [1,0,0,1,1,0,1] ? a
S = [1,0,0,1,1,1,0]
S = [1,0,1,0,0,1,1]
no
One logical way to approach this: find what comes before a 1, then what comes after a 1 and before a 0, and a rest. Then, you need to swap the 1 and 0 so that you have Before 1, 0, after 1 before 0, 1, after 0.
Start small. First, to just split the list whenever you have a 1, so that you have Before and After, you can use append/3 like this, using the list from your example:
?- append(Before, [1|After], [1,0,0,1,1,1,0]).
Before = [],
After = [0, 0, 1, 1, 1, 0] ;
Before = [1, 0, 0],
After = [1, 1, 0] ;
Before = [1, 0, 0, 1],
After = [1, 0] ;
Before = [1, 0, 0, 1, 1],
After = [0] ;
false.
You already get the 4 solutions you expect. Now you need to look inside After to see where to put the 1 -- well, you need to put it right after the first 0. So let's split After on a 0, but just once:
?- append(Before, [1|After], [1,0,0,1,1,1,0]),
once( append(Before0, [0|After0], After) ).
Before = Before0, Before0 = [],
After = [0, 0, 1, 1, 1, 0],
After0 = [0, 1, 1, 1, 0] ;
Before = [1, 0, 0],
After = [1, 1, 0],
Before0 = [1, 1],
After0 = [] ;
Before = [1, 0, 0, 1],
After = [1, 0],
Before0 = [1],
After0 = [] ;
Before = [1, 0, 0, 1, 1],
After = [0],
Before0 = After0, After0 = [] ;
false.
Now you have 3 pieces: one before the 1 called Before, one between the 1 and the first 0 called Before0, and a last piece after the first 0 called After0. You just need to put them back together: Before, 0, Before0, 1, After0. You can use the 2-argument append/2 that takes a list of lists in the first argument:
?- append(Before, [1|After], [1,0,0,1,1,1,0]),
once( append(Before0, [0|After0], After) ),
append([Before, [0|Before0], [1|After0]], Result).
Result = [0, 1, 0, 1, 1, 1, 0] ;
Result = [1, 0, 0, 0, 1, 1, 1] ;
Result = [1, 0, 0, 1, 0, 1, 1] ;
Result = [1, 0, 0, 1, 1, 0, 1] ;
false.
(I left only the Result bindings to save space.)
I think you are done at this point.
Thank you for all the answers, this is how I did it:
flip_first_zero([0|L],[1|L]):-!.
flip_first_zero([X|L],[X|L1]):-
flip_first_zero(L,L1).
next([1|L],[0|L1]):-
flip_first_zero(L,L1).
next([X|L],[X|L1]):-
next(L,L1).

Prolog - Multiplying A list with an uninstantiated list

The input to this predicate is S, a list of integers I, and a list of integers T. Assumption is that both S and I are fully instantiated, but not T. The function multiplies the the first element in I with the first element in T then sums it with the second element in I multiplied with the [...] you get the idea. However, the struggle I am having is making this function succeed when T isn't instantiated it. I don't want to use use_module(library(clpfd)) even though it may be easier.
I already have something which multiplies correctly, as a helper. To get rid of the "uninstantiated variable" issue I figured I let a variable = S div head of I, so I'd instantiate a new variable, and I'd do this for each item in list I. Then I'd generate all the permutations such that the multiplication of items in a list summed results to S
mult_prod(A, B, S) :-
sum_prod(A, B, 0, S).
mult_prod([A | As], [B | Bs], Accum, S) :-
Accum1 is Accum + A*B,
mult_prod(As, Bs, Accum1, S).
mult_prod([], [], Accum, Accum).
multSum(S, I, T) :-
My naive solution:
multSum(0, [], []).
multSum(S, [I | Is], [T | Ts]) :-
between(0, S, T),
S1 is S - I * T,
multSum(S1, Is, Ts).
Sample output:
?- multSum(42, [6, 7, 8, 9], T).
T = [0, 0, 3, 2] ;
T = [0, 1, 1, 3] ;
T = [0, 6, 0, 0] ;
T = [1, 0, 0, 4] ;
T = [1, 4, 1, 0] ;
T = [2, 2, 2, 0] ;
T = [2, 3, 0, 1] ;
T = [3, 0, 3, 0] ;
T = [3, 1, 1, 1] ;
T = [4, 0, 0, 2] ;
T = [7, 0, 0, 0] ;
false.
Potential problems:
This was just too easy; I must have overlooked something in your question or totally misinterpreted it.
Tested in SWI Prolog only; relies on between/3. If necessary, you can implement this predicate yourself.
Limited to non-negative numbers.
Exhaustively generates all possibilities, which can be quite a lot.
Probably not the most efficient implementation possible...

Logical equivalence in Prolog

I got two expressions to list all lists of bits using Prolog:
bit(0).
bit(1).
bitlist1([]).
bitlist1([B|Bs]) :-
bit(B),
bitlist1(Bs).
bitlist2([]).
bitlist2([B|Bs]) :-
bitlist2(Bs),
bit(B).
I can't quite see if they are logically equivalent and even if they both really list ALL bit lists.
As I'm using SWI-Prolog I got the following outputs:
?- bitlist1(Bs).
Bs = [] ;
Bs = [0] ;
Bs = [0, 0] ;
Bs = [0, 0, 0] ;
Bs = [0, 0, 0, 0] ;
Bs = [0, 0, 0, 0, 0] ;
Bs = [0, 0, 0, 0, 0, 0] ;
Bs = [0, 0, 0, 0, 0, 0, 0] ;
Bs = [0, 0, 0, 0, 0, 0, 0, 0] ;
Bs = [0, 0, 0, 0, 0, 0, 0, 0, 0] ;
Bs = [0, 0, 0, 0, 0, 0, 0, 0, 0|...] ;
...
?- bitlist2(Bs).
Bs = [] ;
Bs = [0] ;
Bs = [1] ;
Bs = [0, 0] ;
Bs = [1, 0] ;
Bs = [0, 1] ;
Bs = [1, 1] ;
Bs = [0, 0, 0] ;
Bs = [1, 0, 0] ;
Bs = [0, 1, 0] ;
Bs = [1, 1, 0] ;
Bs = [0, 0, 1] ;
Bs = [1, 0, 1] ;
Bs = [0, 1, 1] ;
Bs = [1, 1, 1] ;
Bs = [0, 0, 0, 0] ;
...
bitlist1 starts listing all bit lists containing only zeros and starts listing all others afterwards but this actually can't be seen as Prolog lists an endless stream of bit lists containing only zeros.
bitlist2 lists all combinations of 0 and 1 of every length and afterwards continues with the bit lists with the length higher length.
So they are logically equivalent imo, only the output order of the bit lists differ.
Maybe anyone can confirm my guess or explain why the two expressions aren't logically equivalent? Would be great.
Citing Vannoord
The problem whether two expressions are logically equivalent is undecidable for any `interesting' logic.
Then, because of incompleteness of Prolog search, you should somewhat restrict your proof criteria. I would state the equivalence arise from the fact that
for any given N, it's not possible to find a length(L, N), bitlist1(L), bitlist2(L) that fail.
Indeed
2 ?- length(L,N), bitlist1(L), bitlist2(L).
L = [],
N = 0 ;
L = [0],
N = 1 ;
L = [1],
N = 1 ;
L = [0, 0],
N = 2 ;
L = [0, 1],
N = 2 ;
L = [1, 0],
N = 2 ;
L = [1, 1],
...
On a logical level, both predicates are equivalent, since "," in a rule is interpreted as logical conjunction which is commutative(the easiest way to check this is by looking at the truth tables for A & B -> C and B & A -> C, but also sequent calculus or some other proof calculus does the job).
For pure prolog programs, the set of answers of logically equivalent predicates is the same. Since prolog uses depth first search as a search strategy, one predictae might not terminate in case the others do:
?- bitlist1([a|Xs]).
false.
?- bitlist2([a|Xs]).
^CAction (h for help) ? abort
% Execution Aborted
The reason is that prolog tries to prove the goals one after each other. In the case of bitlist1, the first goal is bit(B) where prolog can immediatly decide that bit(a) does not hold. In the case of bitlist2, prolog first tries to prove bitlist2(Bs) and recursively does this for the tail of the Bs list which leads to an infinite recursion. So even if both predicates are logically equivalent, they behave differently.
For your problem of looking at the solutions, you could try to enumerate the lists in increasing length:
?- length(X,_), bitlist1(X).
X = [] ;
X = [0] ;
X = [1] ;
X = [0, 0] ;
X = [0, 1] ;
X = [1, 0] ;
X = [1, 1] ;
X = [0, 0, 0] ;
X = [0, 0, 1] ;
X = [0, 1, 0] .
?- length(X,_), bitlist2(X).
X = [] ;
X = [0] ;
X = [1] ;
X = [0, 0] ;
X = [1, 0] ;
X = [0, 1] ;
X = [1, 1] ;
X = [0, 0, 0] ;
X = [1, 0, 0] ;
X = [0, 1, 0] .
the length predicate gives the relation between a list and its length. We now rely on the fact that length(X,_) produces lists of free variables of increasing length. Then the goal bitlist(1/2) will be called on a fixed size list and prolog will find all solutions for that size before backtracking and trying the next larger list.
Please note that this trick only reorders solutions, but does not change termination in general:
?- X=[a|Xs], length(X,_), bitlist2(X).
^CAction (h for help) ? abort
% Execution Aborted
This still fails because prolog needs to check all lists X not to start with a, but the check is only done after the recursive goal.
I'm not sure you should be discussing pure logical meaning of a predicate and then demonstrating it with an actual Prolog program.
Your first predicate, for example, will actually never run out of 0. There is no "afterwords", or the "afterwords in the search tree is surely never going to be visited. This is of course if you use it for generating answers; using it for validating does not exhibit this behaviour.
In pure logic, order of operations is irrelevant, since everything is an idempotent function. So as long as you have no cuts or side effects, A, B and B, A are equivalent.

Get list of sets where the sum of each set is X

I'm trying to figure out how to generate a list of sets, where each set has a length of N and the sum of each set is X.
I found this code:
num_split(0,[]).
num_split(N, [X | List]):-
between(1,N,X),
plus(X,Y,N),
num_split(Y,List).
And I can use that to get a list of sets with sum X:
num_split(6,List),length(List,5).
List = [1, 1, 1, 1, 2] ;
List = [1, 1, 1, 2, 1] ;
List = [1, 1, 2, 1, 1] ;
List = [1, 2, 1, 1, 1] ;
List = [2, 1, 1, 1, 1] ;
false.
The problem is that those are all permutations, and I'm looking for combinations. The output I'm looking for should be something like get_combos(Sum,Length,List):
get_combos(6,2,List).
List = [5,1];
List = [4,2];
List = [3,3];
false.
Any pointers?
If you have access to a CLP(FD) library, you can use this code:
:- [library(clpfd)].
get_combos(Sum, Length, List) :-
length(List, Length),
List ins 1 .. Sum,
% all_distinct(List), not really useful here
sum(List, #=, Sum),
chain(List, #<),
label(List).
test:
?- get_combos(10,3,L).
L = [1, 2, 7] ;
L = [1, 3, 6] ;
L = [1, 4, 5] ;
L = [2, 3, 5] ;
Maybe I misunderstood your question. Use this chain
...
chain(List, #=<),
....
to get possible duplicates values:
?- get_combos(10,3,L).
L = [1, 1, 8] ;
L = [1, 2, 7] ;
L = [1, 3, 6] ;
L = [1, 4, 5] ;
L = [2, 2, 6] ;
L = [2, 3, 5] ;
L = [2, 4, 4] ;
L = [3, 3, 4] ;
false.
Enforce an "equal or greater" restriction between successive values in the array.
You can add it on as another predicate:
is_combination([]).
is_combination([_]).
is_combination([A,B|List]) :- A =< B, is_combination([B|List]).
get_combos(Sum, Length, List) :-
num_split(Sum, Length, List),
is_combination(List).
Unfortunately, tacking it on the end of the num_split/3 does not necessarily increase its performance, so adding it directly into the algorithm would be marginally better:
get_combos(_, 0, []).
get_combos(Sum, 1, [Sum]).
get_combos(Sum, Length, [A, B|List]) :-
between(1, Sum, A),
plus(A, NextSum, Sum),
plus(1, NextLength, Length),
get_combos(NextSum, NextLength, [B|List]),
A =< B.
I'm not sure just how much more performance this gets, as the comparison has to be after the recursion, due to the less-than-or-equals operator (=<) requiring both operands to be fully instantiated for it to work.

Resources