Prolog - summing up predicate results - prolog

Let's say i have the following predicate:
func1(X,B,R)
I provide it with a certain X and B and in return it gives me 5 different results for R.
EDIT:
The X and B do not specify a range. rather, X specify an integer (say 120) and B specifies all integers (starting from 1) whose cubic is less than X.
What func1 does is calculating R as the result the remainder.
In this case where X=120:
B = 1, R = 119 (120-1^3)
B = 2, R = 112 (120-2^3)
B = 3, R = 93 (120-3^3)
B = 4, R = 56 (120-4^3)
It would not calculate B=5 since 5^3 = 125 which is greater than 120, so it stops here.
How can i make a predicate such as:
func2(R,S)
That would accept all of the results given by R, sum them up and store them in S?
Thanks!

To start with, since the values of B are totally derivable from the value of X, I wouldn't include both as arguments in func1. I'll introduce a predicate func3/2 which is true if the second argument is derivable from the first (i.e., func3(X, B) is true if B is derivable from X):
func1(X, R) :-
func3(X, B),
...
What will happen if you query func1(120, R) is you'd get one or more results for R. Then you can use findall/3 as I indicated in my comment:
func2(X, S) :-
findall(R, func1(X, R), Rs),
sumlist(Rs, S).
To define func3/2 the cleanest approach would be to use CLP(FD):
:- use_module(library(clpfd)).
func3(X, B) :-
B #>= 0,
(X - B^3) #>= 0,
label([B]).
Here's an example of what func3 does:
?- func3(120, B).
B = 1 ;
B = 2 ;
B = 3 ;
B = 4.
A much less desirable way to do this if you can't use CLP(FD) would be to use between and define the upper limit of B to be the greatest integer not exceeding the cube root of X:
func3(X, B) :-
Limit is floor(exp(log(X) / 3)),
between(1, Limit, B).
Which yields the same result as above.

Related

Counting the number of valuations via Quine algorithm in Prolog

My logic teacher said in passing that Quines algorithm
can be also used to count valuations. Unfortunately I
cannot get my head around how this is done in Prolog?
The program would for example give, using
the syntax from the answer in Quines algorithm:
?- sat_count(X+Y, C).
C = 3
Since the truth table for the disjunction X+Y
has 3 rows that valuate to true:
X Y X+Y
0 0 0
0 1 1
1 0 1
1 1 1
Point of departure is Quines algorithm with its core predicate eval/2 which has the following specification. The source code of the Quine algorithm and the solution to the question can be found here.
/**
* eval(A, R):
* The predicate succeeds in R with a partial evaluated
* Boolean formula. The predicate starts with the leaves
* and calls simp after forming new nodes.
*/
% eval(+Formula, -Formula)
We first experimented with a labeling predicate, that
will list all valuations without counting them. The predicate
has a fast fail feature, if the partially evaluated formula
is false (0) then labeling needs not to proceed, otherwise we
simply probe the boolean values:
/**
* labeling(L, A):
* The predicate labels the variables from the list L in the formula A.
*/
% labeling(+List, +Formula)
labeling(_, A) :- A == 0, !, fail.
labeling([X|L], A) :- value(X), eval(A, B), labeling(L, B).
labeling([], A) :- A == 1.
Here is an example run:
?- labeling([X,Y], X+Y).
X = 0,
Y = 1 ;
X = 1,
Y = 0 ;
X = 1,
Y = 1
From the labeling predicate we derived a counting predicate
using findall/3 from the ISO core standard. Instead of
succeeding at the end we return 1, inbetween we sum the counts.
This does the job and also profits from fast failing:
/**
* count(L, A, N):
* The predicate silently labels the variables from the list L in the
* formula A and succeeds in N with the count of the solutions.
*/
% count(+List, +Formula, -Integer)
count(_, A, C) :- A == 0, !, C = 0.
count([X|L], A, D) :-
findall(C, (value(X), eval(A, B), count(L, B, C)), R),
sum(R, 0, D).
count([], A, 1) :- A == 1.
Here is an example run:
?- count([X,Y], X+Y, C).
C = 3
The implementation might profit from some optimizations that we didn't implement. For example assigning values to a variable that does not anymore occure in the formula could be optimized away.

CLP(B) weighted sat_count/3 in Prolog

For the CLP(B) library of SWI-Prolog,
I want to implement a weighted version of sat_count/2
sat_count(Sat0, N) :-
catch((parse_sat(Sat0, Sat),
sat_bdd(Sat, BDD),
sat_roots(Sat, Roots),
roots_and(Roots, _-BDD, _-BDD1),
% we mark variables that occur in Sat0 as visited ...
term_variables(Sat0, Vs),
maplist(put_visited, Vs),
% ... so that they do not appear in Vs1 ...
bdd_variables(BDD1, Vs1),
partition(universal_var, Vs1, Univs, Exis),
% ... and then remove remaining variables:
foldl(universal, Univs, BDD1, BDD2),
foldl(existential, Exis, BDD2, BDD3),
variables_in_index_order(Vs, IVs),
foldl(renumber_variable, IVs, 1, VNum),
bdd_count(BDD3, VNum, Count0),
var_u(BDD3, VNum, P),
% Do not unify N directly, because we are not prepared
% for propagation here in case N is a CLP(B) variable.
N0 is 2^(P - 1)*Count0,
% reset all attributes and Aux variables
throw(count(N0))),
count(N0),
N = N0).
I did not find a detailed documentation of the library for modifying the code.
How to implement a weighted version of sat_count/2?
EDIT 1 (01/11/2017):
Thank you #mat for your reply, I can't add comments because I've not enough reputation.
weighted_sat_count/3 should take a list of couples of weights, one for each variable (a weight for True and a weight for False state) and then the other two parameters are the same of sat_count/2.
The Count is the sum of weights of each admissible assignment. The weight of each admissible assignment is the product of the weight of each variable.
The algorithm to calculate the result is:
bdd_weight(BDD_node)
if BDD_node is 1-terminal return 1
if BDD_node is 0-terminal return 0
t_child <- 1-child of BDD_node
f_child <- 0-child of BDD_node
return (weight[BDD_node, 1] * bdd_weight(t_child) + weight[BDD_node, 0] * bdd_weight(f_child))
The algorithm can be more efficient with a map of visited node associated with calculated weight.
weight[,] is the list of couples of weights, 1 for True and 0 for False.
EDIT 2 (03/11/2017):
For example:
A+B+C, a simple SAT formula
List of couple for weights: [(0.7, 0.3), (0.9, 0.1), (0.5, 0.5)], one for each varible
?- weighted_sat_count([(0.7, 0.3), (0.9, 0.1), (0.5, 0.5)], +([A, B, C]), Count).
Count =
0.7*0.9*0.5 +
0.3*0.9*0.5 +
0.7*0.1*0.5 +
...
A non-efficient solution, based on modifying another part of a simple sat solver, starts with looking at a more simpler count code:
% my_sat_count(+List, -Integer)
my_sat_count([X|L], C) :-
findall(D, (X=0, my_sat_count(L,D);
X=1, my_sat_count(L,D)), H),
sum_list(H, C).
my_sat_count([], 1).
% sum_list(+List, -Number)
sum_list([D|L], C) :-
sum_list(L, H),
C is D+H.
sum_list([], 0).
To see that this simple code works, lets make an example (can be run in both SWI-Prolog or Jekejeke Prolog with the Minlog Extension):
Jekejeke Prolog 2, Runtime Library 1.2.5
(c) 1985-2017, XLOG Technologies GmbH, Switzerland
?- use_module(library(finite/clpb)).
% 8 consults and 0 unloads in 93 ms.
Yes
?- sat(X#Y#Z), labeling([X,Y,Z]).
X = 0, Y = 0, Z = 1 ;
X = 0, Y = 1, Z = 0 ;
X = 1, Y = 0, Z = 0 ;
X = 1, Y = 1, Z = 1
?- sat(X#Y#Z), my_sat_count([X,Y,Z],N).
N = 4,
Now adding weighting is a simple extension as follows:
% my_weighted_sat_count(+List, +Pairs, -Float)
my_weighted_sat_count([X|L], [(P,Q)|R], C) :-
findall(D, (X=0, my_weighted_sat_count(L,R,J), D is P*J;
X=1, my_weighted_sat_count(L,R,J), D is Q*J), H),
sum_list(H, C).
my_weighted_sat_count([], _, 1.0).
Here are some example runs:
?- sat(X#Y#Z), my_weighted_sat_count([X,Y,Z],
[(0.5,0.5),(0.4,0.6),(0.3,0.7)],W).
W = 0.5
?- sat(X#Y#Z), my_weighted_sat_count([X,Y,Z],
[(0.3,0.7),(0.3,0.7),(0.3,0.7)],W).
W = 0.532

Prolog - Multiples of a Number Below an Upper Limit

I am currently making a program in Prolog that will calculate all of the multiples (including itself) of a number, that do not exceed the value of another number. I was testing with the query below:
?- multiples(4,12,R,0)
This query would list all multiples of 4 that are less than or equal to 12 eg. 4, 8, 12. The R would return the result and 0 is where I was intending to implement a counter that would count up for each multiplication eg. 4*1,4*2,4*3. I am stuck and I am not sure if it would be a better design to simply add the multiples and check if it is below the upper bound or if it can be done with a counter or accumulator.
multiples(N,U,R,Ctr) :-
N =< U,
R is Ctr * N,
R =< U,
increment(Ctr,Ctr2),
multiples(N,U,R,Ctr2).
increment(Num, Num1) :-
Num1 is Num+1.
I believe my program is failing at the recursive step of calling multiples from within itself. I know that recursion needs a base case to allow it to exit, but I am completely stuck here and would appreciate some direction.
The problem with you approach is that there is no basecase: indeed your algorithm will always produce false. It will unify R with N, then do the recursion and that recursion will try to unify R with 2*N which will fail.
Well an idea could be to use an accumulator to which you add the delta each time. Something like:
multiples(N,U,R) :-
multiples(N,N,U,R).
multiples(_,C,U,C) :-
C =< U.
multiples(N,C,U,R) :-
C =< U,
C1 is C+N,
multiples(N,C1,U,R).
So here we call multiples(3,12,R). and it will result in:
?- multiples(4,12,R).
R = 4 ;
R = 8 ;
R = 12 ;
false.
CLP(FD) is very helpful here:
:- use_module(library(clpfd)).
multiple(Multiplicand, Max, Multiple) :-
MaxMultiplier #= Max // Multiplicand,
label([MaxMultiplier]),
Multiplier in 1 .. MaxMultiplier,
Multiple #= Multiplier * Multiplicand,
label([Multiple]).
?- multiple(4, 12, M).
M = 4 ;
M = 8 ;
M = 12.
?-
With CLP(FD) in this case, you can also query with the first argument as a variable:
|?- multiple(N, 12, 8).
N = 8 ;
N = 4 ;
N = 2 ;
N = 1.
Or both the multiplier and result:
?- multiple(N, 4, M).
N = M, M = 3 ;
N = M, M = 4 ;
N = M, M = 2 ;
N = 2,
M = 4 ;
N = M, M = 1 ;
N = 1,
M = 2 ;
N = 1,
M = 3 ;
N = 1,
M = 4.
?-
If you want to collect them in a list, you can use findall/3:
?- findall(Multiple, multiple(4, 12, Multiple), Multiples).
Multiples = [4, 8, 12].
?-

Successor Arithmetic Prolog Mod function

How to write mod/3 function for successor arithmetic (Peano's Numbers) in prolog?
Think of it this way:
If you want to find the mod of 10 and 4, you divide 10 by 4 and return the reminder. But since divide is multiple subtractions we will use the multiple subtraction logic here.
For Example: 10 mod 4 is same as 10-4 mod 4 which is 6 mod 4 which is again same as 6-4 mod 4 = 2 mod 4. Since the first element (2) is less than the second (4), we terminate the program here and return first element (2).
mod(_, 0, 0). Says that anything mod 0 is 0.
mod(0, _ , 0). Says that 0 mod anything is 0.
mod(X, s(0), 0). Says that anything mod 1 is 0.
This is the tricky part:
mod(A, B, N) :- minus(A, B, R), (R #< B -> N = R ; mod(R, B, N)). This uses the multiple minus logic. If first removes second from first and then checks if first is smaller that the second. If yes, recursively call the mod function. If not return the first element.
s(0).
s(X):- X.
plus(0, Y, Y).
plus(s(X), Y, s(Z)):- plus(X , Y , Z).
minus(A, B, C) :- plus(C, B, A).
mod(_, 0, 0).
mod(0, _ , 0).
mod(X, s(0), 0).
mod(A, B, N) :- minus(A, B, R), (R #< B -> N = R ; mod(R, B, N)).
Thank you #Toby for the edit request.

How to add domain variable to global_cardinality?

I'm trying to add a constraint global_cardinality to my program and in the manual of SICStus Prolog is written:
global_cardinality(+Xs,+Vals)
global_cardinality(+Xs,+Vals,+Options)
where Xs = [X1,...,Xd] is a list of integers or domain variables, and
Vals = [K1-V1,...,Kn-Vn] is a list of pairs where each key Ki is a
unique integer and Vi is a domain variable or an integer. True if
every element of Xs is equal to some key and for each pair Ki-Vi,
exactly Vi elements of Xs are equal to Ki.
Now I can write:
global_cardinality([A,B,C], [1-2, 2-1]).
to say that the number 1 will be used twice. The number 2 will be used just once.
But I would like to say that the number 1 will be used: once, twice or three times
According to the manual I need a domain variable but what is the proper syntax for that?
?- X in 1..3, global_cardinality([A,B,C], [1-X, 2-1]).
not sure about this, but from SWI-Prolog page I think you could try
...global_cardinality([A,B,C], [1-X, 2-1]), (X #= 1 #\/ X #= 2 #\/ X #= 2)...
or
?- global_cardinality([A,B,C], [1-X, 2-1]), X in 1..3, label([A,B,C]).
A = B, B = 1,
C = X, X = 2 ;
A = C, C = 1,
B = X, X = 2 ;
A = X, X = 2,
B = C, C = 1.

Resources