As a prolog newbie, I wanted to try to implement a binary sudoku solver.(Code is below, swi-prolog). Binary sudoku is explained here : https://cstheory.stackexchange.com/questions/16982/how-hard-is-binary-sudoku-puzzle
However, when performing the following query :
binarySudoku([[1,0],[0,1]]). I get "true."
binarySudoku([[1,_],[_,_]]). I get "false."
Now obviously it shouldn't return false as there is a solution... Why is this happening/how can I fix this?
:-use_module(library(clpfd)).
validRow(Row) :-
Row ins 0..1,
length(Row,L),
sum(Row,#=,L/2).
matrixNth(Matr,X,Y,El) :-
nth1(Y,Matr,CurRow),
nth1(X,CurRow,El).
allDifferent([]).
allDifferent([X|Y]) :-
not(member(X,Y)),
allDifferent(Y).
invalid(Rows,X,Y) :-
AboveY is Y-1,
BelowY is Y+1,
matrixNth(Rows,X,Y,1),
matrixNth(Rows,X,AboveY,1),
matrixNth(Rows,X,BelowY,1).
invalid(Rows,X,Y) :-
LeftX is X-1,
RightX is X+1,
matrixNth(Rows,X,Y,1),
matrixNth(Rows,LeftX,Y,1),
matrixNth(Rows,RightX,Y,1).
binarySudoku(Rows) :-
length(Rows,Height),
transpose(Rows,Cols),
length(Cols,Height),
maplist(validRow,Rows),
foreach(between(1,Height,X),foreach(between(1,Height,Y),not(invalid(Rows,X,Y)))),
allDifferent(Rows).
Instead of (\+)/1, which is not logically sound in this case, use the pure constraint dif/2: Your code works as expected of you change the line not(member(X,Y)) to:
maplist(dif(X), Y)
Example query (notice that I also use a_more_readable_naming_convention insteadOfMixingTheCases):
?- binary_sudoku([[1,A],[B,C]]), label([A,B,C]).
A = B, B = 0,
C = 1 ;
false.
+1 for using CLP(FD), which is a good fit for this task.
Related
I have an add2 predicate which resolves like this where s(0) is the successor of 0 i.e 1
?- add2(s(0)+s(s(0)), s(s(0)), Z).
Z = s(s(s(s(s(0)))))
?- add2(0, s(0)+s(s(0)), Z).
Z = s(s(s(0)))
?- add2(s(s(0)), s(0)+s(s(0)), Z).
Z = s(s(s(s(s(0)))))
etc..
I'm trying to do add in a predecessor predicate which will work like so
?- add2(p(s(0)), s(s(0)), Z).
Z = s(s(0))
?- add2(0, s(p(0)), Z).
Z = 0
?- add2(p(0)+s(s(0)),s(s(0)),Z).
Z = s(s(s(0)))
?- add2(p(0), p(0)+s(p(0)), Z).
Z = p(p(0))
I can't seem to find a way to do this. My code is below.
numeral(0).
numeral(s(X)) :- numeral(X).
numeral(X+Y) :- numeral(X), numeral(Y).
numeral(p(X)) :- numeral(X).
add(0,X,X).
add(s(X),Y,s(Z)) :- add(X,Y,Z).
add(p(X),Y,p(Z)) :- add(X,Y,Z).
resolve(0,0).
resolve(s(X),s(Y)) :-
resolve(X,Y).
resolve(p(X),p(Y)) :-
resolve(X,Y).
resolve(X+Y,Z) :-
resolve(X,RX),
resolve(Y,RY),
add(RX,RY,Z).
add2(A,B,C) :-
resolve(A,RA),
resolve(B,RB),
add(RA,RB,C).
In general, adding with successor arithmetic means handling successor terms, which have the shape 0 or s(X) where X is also a successor term. This is addressed completely by this part of your code:
add(0,X,X).
add(s(X),Y,s(Z)) :- add(X,Y,Z).
Now you have to make a decision; you can either handle the predecessors and the addition terms here, in add/3, or you can wrap this predicate in another one that will handle them. You appear to have chosen to wrap add/3 with add2/3. In that case, you will definitely need to create a reducing term, such as you've built here with resolve/2, and I agree with your implementation of part of it:
resolve(0,0).
resolve(s(X),s(Y)) :-
resolve(X,Y).
resolve(X+Y,Z) :-
resolve(X,RX),
resolve(Y,RY),
add(RX,RY,Z).
This is all good. What you're missing now is a way to handle p(X) terms. The right way to do this is to notice that you already have a way of deducting by one, by using add/3 with s(0):
resolve(p(X), R) :-
resolve(X, X1),
add(s(0), R, X1).
In other words, instead of computing X using X = Y - 1, we are computing X using X + 1 = Y.
Provided your inputs are never negative, your add2/3 predicate will now work.
I wrote a test program with bindings (facts) between atoms and numbers.
bind(a, 3).
bind(b, 4).
bind(c, 5).
As part of a toy interpreter, I want to be able to perform additions on these atoms using Prolog's native arithmetic operators. For instance, I want to be able to run this query:
% val(X) is the value bound to X
?- X is val(a) + val(b).
X = 7.
However, I'm struggling to find a way to allow this addition. My first approach would have been this one:
% val(X, Y): Y is the value bound to X
val(X, Y) :- bind(X, Y).
% Make val an arithmetic function
:- arithmetic_function(val/1).
However, arithmetic_function/1 is no longer part of Prolog (or at least SWI-Prolog says it's deprecated), so I can't use it. Then I believed the best solution would be to overload the + operator to take this into account:
% val(X, Y): Y is the value bound to X
val(val(X), Y) :- bind(X, Y).
% Overload the + operator
+(val(_X, XVal), val(_Y, YVal)) :- XVal + YVal.
But here I've got my syntax all messed up because I don't really know how to overload a native arithmetic operation. When I type in the sample query from before, SWI-Prolog says ERROR: Arithmetic: ``val(a)' is not a function.
Would you have hints about a possible solution or a better approach or something I missed?
From the docs, I tought you should use function_expansion/3.
But I'm unable to get it to work, instead, goal_expansion could do, but isn't very attractive... for instance, if you save the following definitions in a file bind.pl (just to say)
:- module(bind, [test/0]).
:- dynamic bind/2.
bind(a, 3).
bind(b, 4).
bind(c, 5).
% :- multifile user:goal_expansion/2.
user:goal_expansion(val(X), Y) :- bind(X, Y).
user:goal_expansion(X is Y, X is Z) :- expand_goal(Y, Z).
user:goal_expansion(X + Y, U + V) :- expand_goal(X, U), expand_goal(Y, V).
test :-
X is val(a) + val(b), writeln(X).
and consult it, you can run your test:
?- test.
7
edit
after Paulo suggestion, here is an enhanced solution, that should work for every binary expression.
user:goal_expansion(X is Y, X is Z) :- expr_bind(Y, Z).
expr_bind(val(A), V) :- !, bind(A, V).
expr_bind(X, Y) :-
X =.. [F, L, R], % get operator F and Left,Right expressions
expr_bind(L, S), % bind Left expression
expr_bind(R, T), % bind Right expression
Y =.. [F, S, T]. % pack bound expressions back with same operator
expr_bind(X, X). % oops, I forgot... this clause allows numbers and variables
having defined user as target module for goal_expansion, it works on the CLI:
?- R is val(a)*val(b)-val(c).
R = 7.
edit
now, let's generalize to some other arithmetic operators, using the same skeleton expr_bind uses for binary expressions:
user:goal_expansion(X, Y) :-
X =.. [F,L,R], memberchk(F, [is, =<, <, =:=, >, >=]),
expr_bind(L, S),
expr_bind(R, T),
Y =.. [F, S, T].
and unary operators (I cannot recall no one apart minus, so I show a simpler way than (=..)/2):
...
expr_bind(-X, -Y) :- expr_bind(X, Y).
expr_bind(X, X).
Now we get
?- -val(a)*2 < val(b)-val(c).
true.
One way to do it is using Logtalk parametric objects (Logtalk runs on SWI-Prolog and 11 other Prolog systems; this makes this solution highly portable). The idea is to define each arithmetic operation as a parametric object that understands an eval/1 message. First we define a protocol that will be implemented by the objects representing the arithmetic operations:
:- protocol(eval).
:- public(eval/1).
:- end_protocol.
The basic parametric object understands val/1 and contains the bind/2 table:
:- object(val(_X_), implements(eval)).
eval(X) :-
bind(_X_, X).
bind(a, 3).
bind(b, 4).
bind(c, 5).
:- end_object.
I exemplify here only the implementation for arithmetic addition:
:- object(_X_ + _Y_, implements(eval)).
eval(Result) :-
_X_::eval(X), _Y_::eval(Y),
Result is X + Y.
:- end_object.
Sample call (assuming the entities above are saved in an eval.lgt file):
% swilgt
...
?- {eval}.
% [ /Users/pmoura/Desktop/eval.lgt loaded ]
% (0 warnings)
true.
?- (val(a) + val(b))::eval(R).
R = 7.
This can be an interesting solution if you plan to implement more functionality other than expression evaluation. E.g. a similar solution but for symbolic differentiation of arithmetic expressions can be found at:
https://github.com/LogtalkDotOrg/logtalk3/tree/master/examples/symdiff
This solution will also work in the case of runtime generated expressions (term-expansion based solutions usually only work at source file compile time and at the top-level).
If you're only interested in expression evaluation, Capelli's solution is more compact and retains is/2 for evaluation. It can also be made more portable if necessary using Logtalk's portable term-expansion mechanism (but note the caveat in the previous paragraph).
This is perhaps not exactly what I was looking for, but I had an idea:
compute(val(X) + val(Y), Out) :-
bind(X, XVal),
bind(Y, YVal),
Out is XVal + YVal.
Now I can run the following query:
?- compute(val(a) + val(c), Out).
Out = 8.
Now I need to define compute for every arithmetic operation I'm interested in, then get my interpreter to run expressions through it.
I'm trying to trigger backtracking on a goal but in a dynamic way, if it's possible. To better exemplify my issue let's say we have the following PROLOG code:
num(1).
num(2).
num(3).
num(4).
num(5).
Then I head to SWI-Prolog and call: num(X). This triggers backtracking looking for all solutions, by typing ; .
What I would like is to remove those facts (num(1),num(2), etc) and replace that code with something thata generates those facts dynamically. Is there any way in which I can achieve this? Someting of the sorts,maybe?
num(X):- for X in 1..5
that yields the same solutions as the code above?
As far as I know, the findall predicate returns a list, which is not what I'm looking for. I would like to backtrack through all answers and look through them using ; in the console.
Yes there is, and you were already very close!
:- use_module(library(clpfd)).
num(X) :-
X in 1..5.
?- num(X).
X in 1..5.
?- num(X), X #>3.
X in 4..5.
?- num(X), labeling([], [X]).
X = 1
; X = 2
; X = 3
; X = 4
; X = 5.
SWI-Prolog has the (non-ISO) predicate between/3 for that:
num(X) :- between(1, 5, X).
You can implement the predicate (for other Prologs and for further tweaking) like this:
between2(A, A, A) :- !. % green cut
between2(A, B, A) :- A < B.
between2(A, B, C) :-
A < B,
A1 is A + 1,
between2(A1, B, C).
The signature for both between/3 and between2/3 is (+From,+To,?X). It means that the From and To must be bound and X can be either bound or not. Also note that From and To must be integers such that From <= To. (Oh, and these integers must be written using Arabic numerals with an optional plus or minus sign before. And using ASCII. Is something non-obvious still missed? And the integers must not be too large or too small, although SWI-Prolog is usually compiled with unbounded integer support, so both between(1, 100000000000000000000000000000000000000000000, X) and between2(1, 100000000000000000000000000000000000000000000, X) usually work.)
I wanted to ask how I can simplify expressions like:
1+2+a*5+0/b-c*0
= 3+a*5
And especially how can I separate such expressions in lists.
It's actually kind of fun in Prolog, because you don't need to do anything too magical to make it work.
?- X-Y = 1+2+a*5+0/b-c*0.
X = 1+2+a*5+0/b,
Y = c*0.
So you could start by doing something like this:
simplify(C, C) :- atom(C) ; number(C).
simplify(X+Y, X1+Y1) :- simplify(X, X1), simplify(Y, Y1).
simplify(X*Y, X1*Y1) :- simplify(X, X1), simplify(Y, Y1).
simplify(X/Y, X1/Y1) :- simplify(X, X1), simplify(Y, Y1).
simplify(X-Y, X1-Y1) :- simplify(X, X1), simplify(Y, Y1).
This is an identity transform: it doesn't do anything.
?- simplify(1+2+a*5+0/b-c*0, Result).
Result = 1+2+a*5+0/b-c*0.
Now you can add rules for specific cases:
simplify(X*0, 0).
simplify(0*X, 0).
Now you get multiple results:
?- simplify(1+2+a*5+0/b-c*0, Result).
Result = 1+2+a*5+0/b-c*0 ;
Result = 1+2+a*5+0/b-0 ;
You could add a rule for constant folding:
simplify(X+Y, C) :- number(X), number(Y), C is X+Y.
You know, just have fun with it.
Lists aren't really any easier to work with, but you can make them using the "univ" operator: =..:
?- 1+2+a*5+0/b-c*0 =.. R.
R = [-, 1+2+a*5+0/b, c*0].
It's possible to simplify expressions in Prolog using unification, but this sometimes leads to unexpected results. In this example, two different variables in an expression are unified when "matching" a pattern, even if they were intended to be distinct:
:- initialization(main).
simplify(A+A,2*A).
main :-
simplify(A+B,C),
writeln(C).
In this case, simplify(A+B,C) would unify A with B.
To solve this problem, I use subsumes_term/2 to match a pattern without unifying the variables in an expression. subsumes_term(A+A,Input) will not match A+B unless A is already unified with B:
simplify(Input,2*A) :-
subsumes_term(A+A,Input).
This subsumes_term/2 predicate is often useful for metaprogramming: I used it to write a Prolog-to-Minizinc compiler.
I have created a program, list(X,Y) to check whether all the elements in list Y are smaller than X.
The codes are as follows.
list(X,[]).
list(X,[Y|Z]):-X>Y,list(X,Z).
It works fine when I type list(3,[1,2]). However, if I type list(3,Y) in order to find lists which only contain elements smaller than 3, there is an error.
?- list(3,[1,2]).
true .
?- list(3,Y).
Y = [] ;
ERROR: >/2: Arguments are not sufficiently instantiated
I have read some posts which got the same error, but I still don't understand which part of my codes goes wrong.
Here comes a similar example found from internet.
greater(X,Y,Z) returns the part Z of Y that is greater than X.
greater(X,[],[]).
greater(X,[H|Y],[H|Z]) :- H>X, greater(X,Y,Z).
greater(X,[H|Y],Z) :- H=<X, greater(X,Y,Z).
?- greater(2,[1,2,3], Y).
Y = [3].
The question is, what is the difference between the codes of greater(X,Y,Z) and list(X,Y) so that there is no error when calling greater(2,[1,2,3], Y)..
Thanks for any help provided.
Since - judging from your comment - you seem to be reasoning over integers: That's a textbook example for using finite domain constraints, which are available in almost all modern Prolog implementations and generalize integer arithmetic so that you can use it in all directions.
Your code works exactly as expected with, among others, B-Prolog, GNU Prolog, SICStus, SWI and YAP if you just use the finite domain constraint (#>)/2 instead of the lower-level arithmetic primitive (>)/2:
:- use_module(library(clpfd)).
list(X, []).
list(X, [Y|Z]):- X#>Y, list(X,Z).
Constraints allow you to use this predicate, which you can also express with maplist/2 as in the queries below, in all directions:
?- maplist(#>(3), [1,2]).
true.
?- maplist(#>(X), [1,2]).
X in 3..sup.
?- maplist(#>(3), [A,B]).
A in inf..2,
B in inf..2.
?- maplist(#>(X), [Y,Z]).
Z#=<X+ -1,
Y#=<X+ -1.
Even the most general query, where none of the arguments is instantiated, gives useful answers:
?- maplist(#>(X), Ls).
Ls = [] ;
Ls = [_G1022],
_G1022#=<X+ -1 ;
Ls = [_G1187, _G1190],
_G1190#=<X+ -1,
_G1187#=<X+ -1 ;
etc.
EDIT: Also the example you now added can be made much more general with finite domain constraints:
:- use_module(library(clpfd)).
greater(_, [], []).
greater(X, [H|Y], [H|Z]) :- H #> X, greater(X, Y, Z).
greater(X, [H|Y], Z) :- H #=< X, greater(X, Y, Z).
You can now use it in all directions, for example:
?- greater(X, [E], Ls).
Ls = [E],
X#=<E+ -1 ;
Ls = [],
X#>=E.
This is not possible with the original version, whose author may not have been aware of constraints.