How to express infinity in Prolog? - random

I am trying to use random/3
random(+L:int, +U:int, -R:int)
Is there any thing that can be used for representing infinity?
For Example:
random(0, Infinity, Random_Number).
Is it possible to achieve this with random? Or is there any other simple alternative?
P.S. I have made clpfd programs where I have used sup ( Supremum ), but I am not working with clpfd.

What an amusing discussion in the comments. My underdeveloped intuition for infinite numbers and math tells me:
There is a finite number of integers that can be represented on a physical computer using a consistent representation. So there will be an infinity of other integers that cannot be represented. So, if you randomly pick any number, the probability that you can represent it on your machine is 0. You might as well define:
random_between(0, infinite, infinite).
Transfinite numbers might be one place to start reading, but who am I to say. You need a mathematician for that kind of questions, not a programming pedestrian.
Maybe you should ask at https://math.stackexchange.com/?
To your question: you can represent the concept of infinity with a symbol, for example the atom infinite. Then you need to decide how you treat that concept in your algebra, and provide rules for it. The random_between/3 above is just one example. For inspiration, check out how floating point numbers handle infinity.

I think the discussion in the comments has taken a less than useful turn. David is right that there is no way to get a uniform integer without an upper bound, but it's not clear if that's what you want. There are absolutely ways of getting unbounded random integers from a skewed distribution, where numbers closer to 0 will be more likely than numbers further away from 0, but no integer, not even one with 10000 trillion digits, is impossible. (As long as you don't exceed Prolog's memory.)
Here's a simple generator. First, lists of random length:
random_length(List) :-
random(P),
( P > 0.25
-> List = [_ | Tail],
random_length(Tail)
; List = [] ).
Examples:
?- random_length(List).
List = [].
?- random_length(List).
List = [_2004, _2022, _2040, _2058, _2076].
?- random_length(List).
List = [].
?- random_length(List).
List = [_2004, _2022, _2040, _2058].
Next, random-length lists of random bits:
random_bit(Bit) :-
random(P),
( P > 0.5
-> Bit = 1
; Bit = 0 ).
random_bits(Bits) :-
random_length(Bits),
maplist(random_bit, Bits).
Examples:
?- random_bits(Bits).
Bits = [0].
?- random_bits(Bits).
Bits = [1, 0, 1, 1, 0, 0].
?- random_bits(Bits).
Bits = [].
?- random_bits(Bits).
Bits = [0, 0, 0].
And then we can evaluate this lists of bits as a number, let's say using this approach:
bits_value([], 0).
bits_value([Bit | Bits], Value) :-
bits_value(Bits, TailValue),
Value is TailValue * 2 + Bit.
Examples:
?- random_bits(Bits), bits_value(Bits, Value).
Bits = [1, 1, 0],
Value = 3.
?- random_bits(Bits), bits_value(Bits, Value).
Bits = [0, 1, 0],
Value = 2.
?- random_bits(Bits), bits_value(Bits, Value).
Bits = [0, 0, 0, 1, 1, 0],
Value = 24.
?- random_bits(Bits), bits_value(Bits, Value).
Bits = [0, 1],
Value = 2.
?- random_bits(Bits), bits_value(Bits, Value).
Bits = [],
Value = 0.
These lists are not bounded in length, but they do tend to be short, hence the values are fairly low. We can modify the 0.25 factor in random_length to make longer lists more likely. For example, with 0.01:
?- random_bits(Bits), bits_value(Bits, Value).
Bits = [0, 0, 0, 0, 0, 0, 1, 0],
Value = 64.
?- random_bits(Bits), bits_value(Bits, Value).
Bits = [0, 1, 0, 1, 1, 1, 0, 0, 0|...],
Value = 137345267061686159418.
?- random_bits(Bits), bits_value(Bits, Value).
Bits = [1, 1, 0, 1, 1, 0, 0, 1, 0|...],
Value = 105607189397659.
?- random_bits(Bits), bits_value(Bits, Value).
Bits = [0, 0, 0, 1, 0, 1, 1],
Value = 104.
There are many things that could be modified in this, for example, lists containing only zeros are not very useful. You could add an "implicit 1" element to such lists. You could also treat one of the bits as a sign bit to allow generation of negative numbers. You could generate random, entirely unbounded rational numbers by generating two random integers P and Q and using P/Q as the random value. And so on.

Related

Prolog: random permutation

I'm trying to get random permutation with prolog. But the problem is
?- permutation([1,2,3,4],L).
gives always L = [1, 2, 3, 4] as first answer. I could fix this by using the query
?- L1=[1,2,3,4], permutation(L1,L2), dif(L1,L2).
But this gives me always L2 = [1, 2, 4, 3] as first answer.
How can I get a random permutation in SWI Prolog?
Isn't [1,2,3,4] random enough? Looks random to me!
But I know what you mean - you want a permutation which looks more random.
Why not roll your own? Just pick the next element out of an ever-shrinking "input list".
This is a bit laborious. Maybe there are more elegant ways?
look_random_dammit([],[]) :- !.
% note that [PickedElement|PermutedList] APPENDS "PickedElement"
% to list being constructed. Appending or prepending does not
% really make a difference here though:
look_random_dammit(ListRemainder,[PickedElement|PermutedList]) :-
ListRemainder \== [],
length(ListRemainder,Length),
succ(Max,Length),
% We are now leaving logicland and asking an oracle to give
% use a random number. "Buckle your seatbelt Dorothy, 'cause
% Kansas is going bye-bye!"
random_between(0,Max,PickedIndex),
nth0(PickedIndex,ListRemainder,PickedElement),
length(Prefix,PickedIndex),
% Constructing a remainder list is probably slow
append([Prefix,[PickedElement],Suffix],ListRemainder) ,
append(Prefix,Suffix,ListRemainderNext),
look_random_dammit(ListRemainderNext,PermutedList).
And so:
?- look_random_dammit([1,2,3,4],P).
P = [2,3,1,4] ;
false.
?- look_random_dammit([],P).
P = [] ;
false.
?- look_random_dammit([1,1,1,2,2],P).
P = [2,1,1,2,1] ;
false.
If we also retained the information about which elements was picked in equence, we could write a predicate that "reverses the permutation" because no information was lost while creating it.
You can try:
?- random_permutation([1,2,3,4], P).
P = [2, 1, 4, 3].
I am just giving an alternate method.
Using findall to get all possible permutations.
Getting the length of the List containing the permutations.
Using random to generate a random number between 0 and the length. This will be used as an index value.
Using nth1 to give us a permutation on the given index.
! (Cut) is used to give only one value. if you want more values then remove it.
Example:-
perm([H|T],Permutation):-
findall(A,permutation([H|T],A),List),
length(List,Length),
random(1,Length,Random),
nth1(Random,List,Permutation),!.
?- perm([1,2,3,4],Permutation).
Permutation = [1, 4, 3, 2]
?- perm([1,2,3,4],Permutation).
Permutation = [3, 1, 2, 4]
?- perm([1,2,3,4],Permutation).
Permutation = [3, 1, 4, 2]

To compare the Equality and Print the Equal value

I want to compare 2 values X and C1 as you can see in code, X is reversed value of C if both values are equal then it should print the compared value please tell me how to do this. It is to print Palindrome Numbers like... 1,11,22,33,44,55,66,77,88,99,101....
go(N):-
write(0),nl,
go(0,N).
go(_,0):- !.
go(A,C):-
A1 is A,
C1 is A1 + 1,
/* write(C1),nl,*/
rev(C1,X),
/* write(X),nl,*/
/* To compare the Value of X and C1 and print if compared value is true*/
NewC is C-1,
go(C1,NewC).
rev(Q,E):-
name(Q, Q1),
reverse(Q1,E1),
name(E,E1).
Describing palindrome numbers is actually a nice task for CLP(FD) and DCGs. First let's describe what the digits of a palindrome number look like:
:- use_module(library(clpfd)).
palindromedigits(Digits) :- % Digits are palindrome digits if
Digits ins 0..9, % they are between 0 and 9
Digits = [H|_], % and the first digit...
H #\= 0, % ... is different from 0
phrase(palindrome, Digits). % and they form a palindrome
palindrome --> % a palindrome is
[]. % an empty list
palindrome --> % or
[_]. % a list with a single element
palindrome --> % or
[A], % an element A
palindrome, % followed by a palindrome
[A]. % followed by an element A
To test if a number is a palindrome, you could turn it into a list of digits and palindromedigits/1 has to hold for that list. To generate such numbers, you could use length/2 to describe lists of all possible lengths, palindromedigits/1 again has to hold for those lists and the digits have to be multiplied by their respective powers of ten and summed up. Since leading zeros are excluded by palindromedigits/1, you'd have to add a fact for 0, if you want to include it in the palindrome numbers. That might look something like this:
palindromenumber(0). % 0 is a palindromenumber
palindromenumber(PN) :- % rule for testing numbers
number(PN), % succeeds if PN is a number
number_codes(PN,C), % C is a list of codes corresponding to the digits
maplist(plus(48),Digits,C), % codes and digits are off by 48
palindromedigits(Digits). % Digits is a palindrome
palindromenumber(PN) :- % rule for generating numbers
var(PN), % succeeds if PN is a variable
length(Digits,_), % Digits is a list of length 0,1,2,...
palindromedigits(Digits), % Digits is a palindrome
digits_number_(Digits,PN,1,0), % Digits correspond to the number PN
label(Digits). % labels the list Digits with actual numbers
Note that the codes corresponding to the digits are off by 48, hence the goal with maplist/3, e.g.:
?- number_codes(123,C), maplist(plus(48),Digits,C).
C = [49, 50, 51], % <- the codes
Digits = [1, 2, 3]. % <- the actual digits
The predicate digits_number_/4 is fairly straight forward. It is called with 1 as the initial power of ten and 0 as the initial accumulator for the number. The digits are multiplied with the power of ten corresponding to their position in the number and subsequently added to the accumulator. If the list of digits is empty, the accumulator holds the number corresponding to the list of digits.
digits_number_([],PN,_,PN).
digits_number_([D|Ds],PN,P,Acc) :-
Acc1 #= Acc + D*B,
P10 #= P*10,
digits_number_(Ds,PN,P10,Acc1).
Note that it doesn't matter that the digits are multiplied with the powers in reverse order, because it's a palindrome number.
Now you can query for palindrome numbers:
?- palindromenumber(PN).
PN = 0 ;
PN = 1 ;
PN = 2 ;
.
.
.
PN = 33 ;
PN = 44 ;
PN = 55 ;
.
.
.
PN = 666 ;
PN = 676 ;
PN = 686 ;
.
.
.
PN = 7667 ;
PN = 7777 ;
PN = 7887
.
.
.
Or you can test if a number is a palindrome:
?- palindromenumber(121).
true ;
false.
?- palindromenumber(123).
false.
?- palindromenumber(12321).
true ;
false.
EDIT
To address the question in your comment, you can do that by describing a relation between such a sequence and it's length. So you'll have a predicate with arity two instead of arity one. Let's give it a nice descriptive name, say firstN_palindromicnumbers/2. The actual realation is described by a predicate with an additional argument that holds the current candidate to be examined. Since you want to start the sequence with 1, that will be the argument firstN_palindromicnumbers_/3 will be called with:
firstN_palindromicnumbers(N,PNs) :-
firstN_palindromicnumbers_(N,PNs,1). % sequence starts with 1
The argument that holds the candidates will be increased by 1 through the recursions, while the first argument, N, will be decreased every time a candidate turns out to be an actual palindromic number. So the predicate eventually ends up with N being 0, an empty list and a candidate we don't care for. That will be the base case. Otherwise the head of the list is the smallest palindromic number in the (remainder of the) sequence. You can reuse the goals number_codes/2 and maplist/3 from above to describe a list of digits corresponding to the current candidate and the DCG palindrome//0 to state that the digits have to be a palindrome. The other goals from the predicate palindromedigits/1 won't be needed, since the candidates will be 1,2,3,..., thus consisting of (at least one) digit(s) from 0 to 9 without leading zeros. You can express this in Prolog like so:
firstN_palindromicnumbers_(0,[],_C). % base case
firstN_palindromicnumbers_(N1,[C0|PNs],C0) :- % case: C0 is a palindrome
N1 #> 0, % sequence is not of desired length yet
number_codes(C0,Codes),
maplist(plus(48),Digits,Codes),
phrase(palindrome, Digits), % digits form a palindrome
N0 #= N1-1, % sequence of length N1-1 has to be described yet
C1 #= C0+1, % C1 is the next candidate
firstN_palindromicnumbers_(N0,PNs,C1). % PNs is the rest of the sequence
firstN_palindromicnumbers_(N1,PNs,C0) :- % case: C0 ain't a palindrome
N1 #> 0, % sequence is not of desired length yet
number_codes(C0,Codes),
maplist(plus(48),Digits,Codes),
\+ phrase(palindrome, Digits), % digits don't form a palindrome
C1 #= C0+1, % C1 is the next candidate
firstN_palindromicnumbers_(N1,PNs,C1). % PNs is the rest of the sequence
Now you can query the predicate for a sequence of palindromic numbers of given length (Note that with SWI-Prolog you might have to hit w to see the entire list):
?- firstN_palindromicnumbers(15,PNs).
PNs = [1, 2, 3, 4, 5, 6, 7, 8, 9|...] [write] % <- hit the w key
PNs = [1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 22, 33, 44, 55, 66] ;
false.
?- firstN_palindromicnumbers(25,PNs).
PNs = [1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 22, 33, 44, 55, 66, 77, 88, 99, 101, 111, 121, 131, 141, 151, 161] ;
false.
You can also use the predicate to check if a given list is the sequence of the first N palindrommic numbers:
?- firstN_palindromicnumbers(N,[1,2,3,4,5]).
N = 5 ;
false.
?- firstN_palindromicnumbers(N,[0|_]).
false.
?- firstN_palindromicnumbers(N,[1,2,3,4,11]).
false.
And the most general query yields the expected answers as well:
?- firstN_palindromicnumbers(N,PNs).
N = 0,
PNs = [] ;
N = 1,
PNs = [1] ;
N = 2,
PNs = [1, 2] ;
N = 3,
PNs = [1, 2, 3] ;
.
.
.

findall Arguments are not sufficiently instantiated

I have simplified my code down to;
findall(T,(T > 0, T < 50),List).
Why would this fail with given error.
Here is your code simplified even further:
?- T > 0.
ERROR: >/2: Arguments are not sufficiently instantiated
The "classical" comparison operations like < and > need all their arguments to be fully instantiated to ground terms; in particular, they cannot be unbound variables. (The same is true for the term on the right-hand-side of the is/2 operator.)
You can not use these operators as generators. Here is one illustration of a possible reason why:
?- T = 1, T > 0.
T = 1.
?- T = 0.1, T > 0.
T = 0.1.
?- T = 0.01, T > 0.
T = 0.01.
?- T = 0.001, T > 0.
T = 0.001.
The > operator works for several different types of numbers, including floating-point numbers. If we wanted it to be a logically reasonable generator, it would have to be able to generate all the floating-point numbers it accepts in the example above. That would almost certainly not be what you want.
There are a few ways to get what you want. As you presumably want integers only, you can use the between/3 predicate provided by many Prolog systems (including SWI):
?- between(1, 49, T).
T = 1 ;
T = 2 ;
T = 3 ;
T = 4 .
?- findall(T, between(1, 49, T), List).
List = [1, 2, 3, 4, 5, 6, 7, 8, 9|...].
Another possibility is to use a constraint programming library. Here is one example session with SWI-Prolog's clpfd library:
?- use_module(library(clpfd)).
true.
?- T #> 0, T #< 50.
T in 1..49.
Note that here, using #> and #< from the clpfd library instead of < and >, we can actually specify these constraints even on an unbound variable. These constraints are remembered for later use, but they do not enumerate actual values for T. You can use them in arithmetic and comparisons, and the system will sometimes reason things out correctly even though it doesn't enumerate concrete values! For example:
?- T #> 0, T #< 50, X #= T - 50, X #> 50.
false.
To get actual values, you call a specific predicate that enumerates them:
?- T #> 0, T #< 50, indomain(T).
T = 1 ;
T = 2 ;
T = 3 ;
T = 4 .
All this gives another possible solution for your problem:
?- findall(T, (T #> 0, T #< 50, indomain(T)), List).
List = [1, 2, 3, 4, 5, 6, 7, 8, 9|...].
If you want filtering, how about writing like this:
bagof(T,(member(T,[0,-4,34,15,76,100,200,43,21]),T>0,T<50),List).
List will be [34,15,43,21].
(though I didn't test)
If you just want to enumurate 1 to 49, ignore this answer(others have already answered)

Prolog Permutations

I'm trying to get more into learning prolog as I'll be taking an AI class at school next semester. I've been able to get down the basics down and can do relation based stuff, however, I've been trying to learn permutations and combinatronics and they seem pretty straightforward, but it led me to a question that I can't figure out how to solve. Say I wanted to know the permutations of 1's and 0's with a certain condition that there must be atleast 4 1's in a row.
I have no idea where I would start to try and find a solution for this, but in the end I want the code to do something like this:
?- placeOnesAndZeros(9,X).
% where 9 is the length of the list/array and X is the permutations
[0,0,0,0,0,0,0,0,0]
[1,1,1,1,0,0,0,0,0]
[0,1,1,1,1,0,0,0,0]
[0,0,1,1,1,1,0,0,0]
[0,0,0,1,1,1,1,0,0]
[0,0,0,0,1,1,1,1,0]
[0,0,0,0,0,1,1,1,1]
[1,1,1,1,0,1,1,1,1]
[1,1,1,1,1,0,0,0,0]
[0,1,1,1,1,1,0,0,0]
[0,0,1,1,1,1,1,0,0]
[0,0,0,1,1,1,1,1,0]
[0,0,0,0,1,1,1,1,1]
[1,1,1,1,1,1,0,0,0]
[0,1,1,1,1,1,1,0,0]
[0,0,1,1,1,1,1,1,0]
[0,0,0,1,1,1,1,1,1]
[1,1,1,1,1,1,1,0,0]
[0,1,1,1,1,1,1,1,0]
[0,0,1,1,1,1,1,1,1]
[1,1,1,1,1,1,1,1,0]
[0,1,1,1,1,1,1,1,1]
[1,1,1,1,1,1,1,1,1]
Thank you in advance!
EDIT CODE:
printList([ ]).
printList([H|T]) :- print(H), nl, printList(T).
eval([],_).
eval([H|T],[1,0]):-member(H,[1,0]),eval(T,[1,0]).
placeOnesAndZeros(N, L):-length(L,N), eval(L,[1,0]).
Generate and test it's the name of the basic technique used to search a solution space. In Prolog, it's practically built in. Just provide a filter discarding what is not required:
?- placeOnesAndZeros(9,L),once(append(_,[1,1,1,1|_],L)).
once/1 is required, otherwise append/3 could succeed multiple times.
To check the correctness of the approach, here is how to count how many solutions we get:
?- aggregate(count,L^H^T^(placeOnesAndZeros(9,L),once(append(H,[1,1,1,1|T],L))),C).
C = 111.
The quantification on variables L,H,T (these last 2 being introduced only to aggregate) can be avoided using aggregate_all:
?- aggregate_all(count,(placeOnesAndZeros(9,L),once(append(_,[1,1,1,1|_],L))),C).
C = 111.
edit
As #lurker noted, my filter isn't correct. Try instead
atLeastFourOnes(L) :- memberchk(1,L), atLeastFourOnes_(L).
atLeastFourOnes_([]).
atLeastFourOnes_([0|L]) :- atLeastFourOnes_(L).
atLeastFourOnes_([1,1,1,1|L]) :- stripOnes(L,R), atLeastFourOnes_(R).
that yields
?- placeOnesAndZeros(9,L),atLeastFourOnes(L).
L = [1, 1, 1, 1, 1, 1, 1, 1, 1] ;
L = [1, 1, 1, 1, 1, 1, 1, 1, 0] ;
L = [1, 1, 1, 1, 1, 1, 1, 0, 0] ;
...
?- aggregate(count,L^(placeOnesAndZeros(9,L),atLeastFourOnes(L)),C).
C = 22.

Generate all permutations of the list [1, 1, 2, 2, ..., n, n] where the number of elements between each pair is even in Prolog

I recently started learning Prolog and I got a task to write a predicate list(N, L) that generates lists L such that:
L has length 2N,
every number between 1 and N occurs exactly twice in L,
between each pair of the same element there is an even number of other elements,
the first occurrences of each number are in increasing order.
The author states that there are N! such lists.
For example, for N = 3 all solutions are:
?- list(3, L).
L = [1, 1, 2, 2, 3, 3] ;
L = [1, 1, 2, 3, 3, 2] ;
L = [1, 2, 2, 1, 3, 3] ;
L = [1, 2, 2, 3, 3, 1] ;
L = [1, 2, 3, 3, 2, 1] ;
L = [1, 2, 3, 1, 2, 3] ;
false.
My current solution looks like:
even_distance(H, [H | _]) :-
!.
even_distance(V, [_, _ | T]) :-
even_distance(V, T).
list(N, [], _, Length, _, _) :-
Length =:= 2*N,
!.
list(N, [New | L], Max, Length, Used, Duplicates) :-
select(New, Duplicates, NewDuplicates),
even_distance(New, Used),
NewLength is Length + 1,
list(N, L, Max, NewLength, [New | Used], NewDuplicates).
list(N, [New | L], Max, Length, Used, Duplicates) :-
Max < N,
New is Max + 1,
NewLength is Length + 1,
list(N, L, New, NewLength, [New | Used], [New | Duplicates]).
list(N, L) :-
list(N, L, 0, 0, [], []).
It does two things:
if current maximum is less than N, add that number to the list, put it on the list of duplicates, and update the max;
select some duplicate, check if there is an even number of elements between it and the number already on the list (ie. that number is on odd position), then add it to the list and remove it from duplicates.
It works, but it's slow and doesn't look really nice.
The author of this exercise shows that for N < 12, his solution generates a single list with average of ~11 inferences (using time/1 and dividing the result by N!). With my solution it grows to ~60.
I have two questions:
How to improve this algorithm?
Can this problem be generalized to some other known one? I know about similar problems based on the multiset [1, 1, 2, 2, ..., n, n] (eg. Langford pairing), but couldn't find something like this.
I'm asking because the original problem is about enumerating intersections in a self-intersecting closed curve. You draw such curve, pick a point and direction and follow the curve, enumerating each intersection when met for the first time and repeating the number on the second meeting: example (with the answer [1, 2, 3, 4, 5, 3, 6, 7, 8, 1, 9, 5, 4, 6, 7, 9, 2, 8]).
The author states that every such curve satisfies the predicate list, but not every list corresponds to a curve.
I had to resort to arithmetic to satisfy the requirement about pairs of integers separated by even count of elements. Would be nice to be able to solve without arithmetic at all...
list(N,L) :- numlist(1,N,H), list_(H,L), even_(L).
list_([D|Ds],[D|Rs]) :-
list_(Ds,Ts),
select(D,Rs,Ts).
list_([],[]).
even_(L) :-
forall(nth0(P,L,X), (nth0(Q,L,X), abs(P-Q) mod 2 =:= 1)).
select/3 is used in 'insert mode'.
edit to avoid arithmetic, we could use this more verbose schema
even_(L) :-
maplist(even_(L),L).
even_(L,E) :-
append(_,[E|R],L),
even_p(E,R).
even_p(E,[E|_]).
even_p(E,[_,_|R]) :- even_p(E,R).
edit
Here is a snippet based on assignment in a prebuilt list of empty 'slots'. Based on my test, it's faster than your solution - about 2 times.
list(N,L) :-
N2 is N*2,
length(L,N2),
numlist(1,N,Ns),
pairs(Ns,L).
pairs([N|Ns],L) :- first(N,L,R),even_offset(N,R),pairs(Ns,L).
pairs([],_).
first(N,[N|R],R) :- !.
first(N,[_|R],S) :- first(N,R,S).
even_offset(N,[N|_]).
even_offset(N,[_,_|R]) :- even_offset(N,R).
My first attempt, filtering with even_/1 after every insertion, was much slower. I was initially focused on pushing the filter immediately after the select/3, and performance was indeed almost good as the last snippet, but alas, it loses a solution out of 6...

Resources