How to input the following data in prolog? - prolog

not(A()) and not(D()) and not(B()) and not(A()).
What's the right way?

The concept of logical negation is already included in Prolog in means of failure. If your implementation doesn't supply it (it can happens) you can think not as
not(P) :- call(P), !, fail.
or
not(P) :- (call(P) -> fail ; true)
Then look at the formula, it can be simplified to have not applied just to single predicates:
~(A & ~D) & ~B & ~A = (~A | D) & ~B & ~A = ~A & ~B
It's just a De Morgan law and a consideration about the fact that D isn't useful to satisfability of the predicate.
then you can combine them:
final_predicate :- not(B), not(A).
EDIT: remember , is AND and ; is OR.

If simply trying to evaluate a propositional logic statement using PROLOG, you could try the following. Start with an encoding of the values of your 'propositions' a, b and d, such as:
a :- true. % this means that a is true.
b :- fail. % this means that b is false
...etc. For example, assuming your statements were:
a :- fail.
b :- fail.
d :- fail.
Then, executing your statement:
?- not(a), not(b), not(d), not(a).
true.
n.b.: The 'propositions' encoded here are 'simulated' - they're actually zero arity first-order predicates as far as PROLOG is concerned.
ps. a :- true. can be simplified to a..
pps. If I'm way off the mark and you're after a way of symbolically manipulating the statement into some other form, such as a normalization, then you need to write what is called a meta-interpreter in PROLOG. Refer to Clocksin and Mellish's Programming in Prolog, Appendix B, 'Clausal Form Program Listings', which might help you.

Related

Tool to solve propositional logic / boolean expressions (SAT Solver?)

I am new to the topic of propositional logic and boolean expressions. So this is why I need help. Here is my problem:
In the car industry you have thousand of different variants of components available to choose from when you buy a car. Not every component is combinable, so for each car there exist a lot of rules that are expressed in propositional logic. In my case each car has between 2000 and 4000 rules.
They look like this:
A → B ∨ C ∨ D
C → ¬F
F ∧ G → D
...
where "∧" = "and" / "∨" = "or" / "¬" = "not" / "→" = "implication".
The variables A, B, C, ... are linked to the components in the bill of material. The data I have consists of pairs of components with their linked variables.
Example:
Component_1, Component_2: (A) ∧ (B)
Component_1, Component_3: (A) ∧ (C ∨ F)
Component_3, Component_5: (B ∨ G)
...
Now, my question is how to solve this problem. Specifically, I would like to know if each combination of the components is possible according to rules above.
Which tool, software and algorithm can solve these type of problems?
Is there a illustrative example?
How can I automate it, so I can check each combination in my list?
Generally, what should I search for in Google to deepen my knowledge in this topic?
Thank you very much for your help!
Olaf
You might want to try a Prolog system with a SAT Solver, such as SWI-Prolog, Jekejeke Minlog, etc... you can readily play with it in the REPL of the Prolog system. To load the SAT solver just type (you don't need to type the ?- itself):
/* in SWI-Prolog */
?- use_module(library(clpb)).
/* in Jekejeke Minlog */
?- use_module(library(finite/clpb)).
You can then use the top-level to search for solutions of a boolean formula, like this example here an xor:
?- sat(X#Y), labeling([X,Y]).
X = 0,
Y = 1 ;
X = 1,
Y = 0.
Here is an example of a kitchen planner code. The kitchen has 3 places,
and we assign a freezer and a stove. The freezer is not allowed to be near to the stove.
The freezer has code 0,1 and the stove has code 1,0. We make use of the card constraint to place the freezer and the stove.
:- use_module(library(finite/clpb)).
freezer([X,Y|L],[(~X)*Y|R]) :-
freezer(L, R).
freezer([], []).
stove([X,Y|L],[X*(~Y)|R]) :-
stove(L, R).
stove([], []).
free([X,Y|L],[(~X)*(~Y)|R]) :-
free(L, R).
free([], []).
allowed([X,Y,Z,T|L]) :-
sat(~((~X)*Y*Z*(~T))),
sat(~(X*(~Y)*(~Z)*T)),
allowed([Z,T|L]).
allowed([_,_]).
allowed([]).
kitchen(L) :-
freezer(L, F), card(1, F),
stove(L, G), card(1, G),
free(L, H), card(1, H),
allowed(L).
What I want to demonstrate with the Prolog code is the benefit, that problem encoding towards a SAT formulation can be done via Prolog code itself. When the above code is run I get the following result as expected:
?- L=[_,_,_,_,_,_], kitchen(L), labeling(L).
L = [0,1,0,0,1,0] ;
L = [1,0,0,0,0,1] ;
No

How this prolog crossword solver works?

I am trying to write a crossword solver I have got this code but I can't Understand some parts of it:
size(5).
black(1,3).
black(2,3).
black(3,2).
black(4,3).
black(5,1).
black(5,5).
words([do,ore,ma,lis,ur,as,po, so,pirus, oker,al,adam, ik]) .
:- use_module(library(lists),[nth1/3, select/3]).
crossword(Puzzle) :-
words(WordList),
word2chars(WordList,CharsList),
make_empty_words(EmptyWords) ,
fill_in(CharsList,EmptyWords),
word2chars(Puzzle,EmptyWords).
word2chars([],[]).
word2chars([Word|RestWords] ,[Chars|RestChars] ) :-
atom_chars(Word,Chars),
word2chars(RestWords,RestChars).
fill_in([],[]).
fill_in([Word|RestWords],Puzzle) :-
select(Word,Puzzle,RestPuzzle),
fill_in(RestWords,RestPuzzle).
make_empty_words(EmptyWords) :-
size(Size),
make_puzzle(Size,Puzzle),
findall(black(I,J),black(I,J),Blacks) ,
fillblacks(Blacks,Puzzle),
empty_words(Puzzle,EmptyWords).
make_puzzle(Size,Puzzle) :-
length(Puzzle,Size),
make_lines(Puzzle,Size).
make_lines([],_).
make_lines([L|Ls],Size) :-
length(L,Size),
make_lines(Ls,Size).
fillblacks([],_).
fillblacks([black(I,J)|Blacks],Puzzle) :-
nth1(I,Puzzle,LineI),
nth1(J,LineI,black),
fillblacks(Blacks,Puzzle).
empty_words(Puzzle,EmptyWords) :-
empty_words(Puzzle,EmptyWords,TailEmptyWords),
size(Size),
transpose(Size,Puzzle,[],TransposedPuzzle),
empty_words(TransposedPuzzle,TailEmptyWords,[] ).
empty_words([],Es,Es).
empty_words([L|Ls],Es,EsTail) :-
empty_words_on_one_line(L,Es,Es1) ,
empty_words(Ls,Es1,EsTail).
empty_words_on_one_line([], Tail, Tail).
empty_words_on_one_line([V1,V2|L],[[V1,V2|Vars]|R],Tail) :-
var(V1), var(V2), !,
more_empty(L,RestL,Vars),
empty_words_on_one_line(RestL,R,Tail) .
empty_words_on_one_line([_| RestL],R, Tail) :-
empty_words_on_one_line(RestL,R,Tail) .
more_empty([],[],[]).
more_empty([V|R],RestL,Vars) :-
( var(V) ->
Vars = [V|RestVars],
more_empty(R,RestL,RestVars)
;
RestL = R,
Vars = []
).
transpose(N,Puzzle,Acc,TransposedPuzzle) :-
( N == 0 ->
TransposedPuzzle = Acc
;
nth_elements(N,Puzzle,OneVert),
M is N - 1,
transpose(M,Puzzle,[OneVert|Acc], TransposedPuzzle)
).
nth_elements(_,[],[]).
nth_elements(N,[X|R],[NthX| S]) :-
nth1(N,X,NthX),
nth_elements(N,R,S).
This code is used for solving crosswords like this:
What are symbols ; -> used for?
My main problem is understanding the rules , transpose and more_empty.
Any explanation to help me understand the code would be appreciated.
-> and ; are Prolog's control flow, like the if-then-else satement in other languages. So:
transpose(N,Puzzle,Acc,TransposedPuzzle) :-
( N == 0 ->
TransposedPuzzle = Acc
;
nth_elements(N,Puzzle,OneVert),
M is N - 1,
transpose(M,Puzzle,[OneVert|Acc], TransposedPuzzle)
).
translates to psuedocode:
def transpose(N, Puzzle, Acc)
if N == 0
return Acc
else
OneVert = nth_elements(N, Puzzle)
transpose(N-1, Puzzle, [OneVert, Acc])
or:
def transpose(N, Puzzle, Acc)
while N > 0
OneVert = nth_elements(N, Puzzle)
Acc = [OneVert, Acc]
N = N - 1
return Acc
That should give you some idea what it does. I suggest you translate the more_empty function into psuedocode yourself (or just step through it in your head), and try to work it out from there.
In addition to the correct answers of Josh and Avi Tshuva stating that a -> b ; c is like "if a then b else c", I would like to explain that -> and ; are individual operators which can be used separately.
; is logical disjunction, ie. logical "or". So x; y means "x or y". This makes the conditional statement a bit confusing because a -> b ; c reads like "a implies b or c" which is obviously not what it means! Even if you parenthesize it like "(a implies b) or c" you get a different meaning from the conditional statement because in this incorrect interpretation, c will always be tried, even if (a implies b) succeeds.
The difference is because -> has some "non-logical" semantics. From SWI-Prolog docs:
:Condition -> :Action If-then and If-Then-Else. The ->/2 construct commits to the choices made at its left-hand side, destroying choice points created inside the clause (by ;/2), or by goals called by this clause. Unlike !/0, the choice point of the predicate as a whole (due to multiple clauses) is not destroyed. The combination ;/2 and ->/2 acts as if defined as:
If -> Then; _Else :- If, !, Then.
If -> _Then; Else :- !, Else.
If -> Then :- If, !, Then.
Please note that (If -> Then) acts as (If -> Then ; fail), making the construct fail if the condition fails. This unusual semantics is part of the ISO and all de-facto Prolog standards.
(note that in the above quote, If, Then etc. are variables!)
So beware of anything with an implicit cut!
These are Prolog's if-then-else control structure.
The syntax is as follows:
condition -> then statements/decelerations ; else
statements/declerations

prolog and translating propositional logic

My ultimate goal is to load a set of propositional formulas in to Prolog from a file in order to deduce some facts. Suppose I have the propositional formula:
p implies not(q).
In Prolog this would be:
not(q) :- p
Prolog does not seem to like the not operator in the head of the rule. I get the following error:
'$record_clause'/2: No permission to redefine built-in predicate `not/1'
Use :- redefine_system_predicate(+Head) if redefinition is intended
I know two ways to rewrite the general formula for p implies q. First, use the fact that the contrapositive is logically equivalent.
p implies q iff not(q) implies not(p)
Second, use the fact that p implies q is logically equivalent to not(p) or q (the truth tables are the same).
The first method leads me to my current problem. The second method is then just a conjunction or disjunction. You cannot write only conjunctions and disjunctions in Prolog as they are not facts or rules.
What is the best way around my problem so that I can express p implies not(q)?
Is it possible to write all propositional formulas in Prolog?
EDIT: Now I wish to connect my results with other propositional formulae. Suppose I have the following rule:
something :- formula(P, Q).
How does this connect? If I enter formula(false, true) (which evaluates to true) into the interpreter, this does not automatically make something true. Which is what I want.
p => ~q === ~p \/ ~q === ~( p /\ q )
So we can try to model this with a Prolog program,
formula(P,Q) :- P, Q, !, fail.
formula(_,_).
Or you can use the built-in \+ i.e. "not", to define it as formula(P,Q) :- \+( (P, Q) ).
This just checks the compliance of the passed values to the formula. If we combine this with domain generation first, we can "deduce" i.e. generate the compliant values:
13 ?- member(Q,[true, false]), formula(true, Q). %// true => ~Q, what is Q?
Q = false.
14 ?- member(Q,[true, false]), formula(false, Q). %// false => ~Q, what is Q?
Q = true ;
Q = false.
You are using the wrong tool. Try Answer Set Programming.

Prolog notBetween function

I need some help here with Prolog.
So I have this function between that evaluates if an element is between other two.
What I need now is a function that evaluates if a member is not between other two, even if it is the same as one of them.
I tried it :
notBetween(X,Y,Z,List):-right(X,Y,List),right(Z,Y,List). // right means Z is right to Y and left the same for the left
notBetween(X,Y,Z,List):-left(X,Y,List),left(Z,Y,List).
notBetween(X,Y,Z,List):-Y is Z;Y is X.
I am starting with Prolog so maybe it is not even close to work, so I would appreciate some help!
When it come to negation, Prolog behaviour must be handled more carefully, because negation is 'embedded' in the proof engine (see SLD resolution to know a little more about abstract Prolog). In your case, you are listing 3 alternatives, then if one will not be true, Prolog will try the next. It's the opposite of what you need.
There is an operator (\+)/2, read not. The name has been chosen 'on purpose' different than not, to remember us that it's a bit different from the not we use so easily during speaking.
But in this case it will do the trick:
notBeetwen(X,Y,Z,List) :- \+ between(X,Y,Z,List).
Of course, to a Prolog programmer, will be clearer the direct use of \+, instead of a predicate that 'hides' it - and requires inspection.
A possibile definition of between/4 with basic lists builtins
between(X,Y,Z,List) :- append(_, [X,Y,Z|_], List) ; append(_, [Z,Y,X|_], List).
EDIT: a simpler, constructive definition (minimal?) could be:
notBetween(X,Y,Z, List) :-
nth1(A, List, X),
nth1(B, List, Y),
nth1(C, List, Z),
( B < A, B < C ; B > A, B > C ), !.
EDIT: (==)/2 works with lists, without side effects (it doesn't instance variables). Example
1 ?- [1,2,3] == [1,2,3].
true.
2 ?- [1,2,X] == [1,2,X].
true.
3 ?- [1,2,Y] == [1,2,X].
false.

How do you translate DCGs into normal definite clauses in PROLOG?

How would you translate the following DCGs into normal definite clauses of PROLOG?
expr_regular --> cor_ini,numero,guion,numero,cor_fin.
cor_ini --> ['['].
numero --> ['0'];['1'];['2'];['3'];['4'];['5'];['6'];['7'];['8'];['9'].
cor_fin --> [']'].
guion --> ['-'].
EDIT: I want to translate the DCG into normal PROLOG clauses cause I can't use both DCGs and normal clauses in the same code(in my case). I have this two pieces of code:
Piece1:
traducir(Xs, Ys) :- maplist(traduccion, Xs, Ys).
traduccion('^',comeza_por).
traduccion('[',inicio_rango).
traduccion('0',cero).
traduccion('-',a).
traduccion('9',nove).
traduccion(']',fin_rango).
An example of how to use it would be:
?- traducir(['[','0','-','9',']'],[]).
true .
And Piece2:
traducir--> cor_ini,numero,guion,numero,cor_fin.
cor_ini --> ['['].
numero --> ['0'];['1'];['2'];['3'];['4'];['5'];['6'];['7'];['8'];['9'].
cor_fin --> [']'].
guion --> ['-'].
An example of how to use it would be:
traducir(['^','[','0','-','9',']'],X).
X = [comeza_por, inicio_rango, cero, a, nove, fin_rango].
I want to join both codes into one to test if traducir is well written (if it follows the DCG) and to translate what you enter into text ,so the final program should able to do the following:
?- traducir(['^','[','0','-','9',']'],X).
X = [comeza_por, inicio_rango, cero, a, nove, fin_rango].
?- traducir(['[','0','-','9',']'],[]).
true .
In SWI-Prolog you can use listing/1 directly on the prolog-toplevel:
?- forall(member(NT,[expr_regular//0,cor_ini//0,numero//0,cor_fin//0,guion//0]),
listing(NT)).
expr_regular(A, F) :-
cor_ini(A, B),
numero(B, C),
guion(C, D),
numero(D, E),
cor_fin(E, F).
cor_ini(['['|A], A).
numero(A, B) :-
( A=['0'|B]
; A=['1'|B]
; A=['2'|B]
; A=['3'|B]
; A=['4'|B]
; A=['5'|B]
; A=['6'|B]
; A=['7'|B]
; A=['8'|B]
; A=['9'|B]
).
cor_fin([']'|A], A).
guion([-|A], A).
true.
That's it! You may profit from looking at the answers of the related question "Is there a way or an algorithm to convert DCG into normal definite clauses in Prolog?".
Your grammar it's exceptionally simple: just terminals. So we can translate to a very specific pattern (beware: no generalization allowed).
expr_regular(S, G) :-
S = [0'[, N1, 0'-, N2, 0']|G], numero(N1), numero(N2).
numero(N) :-
memberchk(N, "0123456789").
The only think worth to note it's ISO standard character notation...
Well I don't really get your question. Anyway, if you don't want to use the nice DCGs syntax for some reason you can still go with things like wildcard_match/2, or reinvent the wheel and use difference lists yourself to re-implement DCGs, or append. For the wildcard_match/2 part:
expr_regular(R) :- wildcard_match('[[][0-9]-[0-9]]', R).

Resources