I'm considering learning Clingo but would like to see if it could solve this logic problem of my own devising - logic

You are the detective in a crime. From your research you know that Jill and John are lying however the others may be telling the truth or lying. What can you deduce from the statements below?
Jill said: IF John is not involved and Joe told the truth THEN Mike is not involved
John said: IF Abby is involved or Sue is involved THEN Joe is involved
Abby said: IF Cindy is not involved or Joe is not involved THEN Mike is involved or Jill is not involved
Cindy said: IF Mike is involved and Joe told the truth THEN John is not involved or Jill is involved
Sue said: IF Joe is involved or Sue is not involved THEN Cindy is involved or Abby is not involved
Mike said: IF Cindy is not involved and Abby is involved THEN John is not involved or Jill is not involved
Joe said: IF Jill is telling the truth or Cindy is lying THEN Sue is telling the truth or Mike is telling the truth
If this is possible it would be helpful to show the coding and output in order to determine the complexity involved.

Any number of frameworks (programming languages, logic systems, constraint-solving frameworks) can handle such problems, with varying degrees of ease. My favorite tools to use are SMT solvers. When paired with a good programming language interface, you can code such problems with ease.
The following is one way to solve this problem, using the z3 SMT solver, and the Haskell bindings called SBV:
{-# LANGUAGE DeriveAnyClass, StandaloneDeriving, TemplateHaskell #-}
{-# OPTIONS_GHC -Wall -Werror #-}
module Puzzle where
import Data.SBV
data Person = Jill | John | Joe | Mike | Abby | Sue | Cindy
mkSymbolicEnumeration ''Person
involved, lying, notInvolved, tellsTruth :: Person -> SBool
involved = uninterpret "involved" . literal
lying = uninterpret "lying" . literal
notInvolved = sNot . involved
tellsTruth = sNot . lying
puzzle :: Goal
puzzle = do
let infixr 1 `said`
said p s = constrain $ tellsTruth p .== s
-- We know Jill and John are lying
constrain $ lying Jill
constrain $ lying John
-- Jill said: IF John is not involved and Joe told the truth THEN Mike is not involved
Jill `said` (notInvolved John .&& tellsTruth Joe) .=> notInvolved Mike
-- John said: IF Abby is involved or Sue is involved THEN Joe is involved
John `said` (involved Abby .|| involved Sue) .=> involved Joe
-- Abby said: IF Cindy is not involved or Joe is not involved THEN Mike is involved or Jill is not involved
Abby `said` (notInvolved Cindy .|| notInvolved Joe) .=> (involved Mike .|| notInvolved Jill)
-- Cindy said: IF Mike is involved and Joe told the truth THEN John is not involved or Jill is involved
Cindy `said` (involved Mike .&& tellsTruth Joe) .=> (notInvolved John .|| involved Jill)
-- Sue said: IF Joe is involved or Sue is not involved THEN Cindy is involved or Abby is not involved
Sue `said` (involved Joe .|| notInvolved Sue) .=> (involved Cindy .|| notInvolved Abby)
-- Mike said: IF Cindy is not involved and Abby is involved THEN John is not involved or Jill is not involved
Mike `said` (notInvolved Cindy .&& involved Abby) .=> (notInvolved John .|| notInvolved Jill)
-- Joe said: IF Jill is telling the truth or Cindy is lying THEN Sue is telling the truth or Mike is telling the truth
Joe `said` (tellsTruth Jill .|| lying Cindy) .=> (tellsTruth Sue .|| tellsTruth Mike)
When run, this prints:
*Puzzle> sat puzzle
Satisfiable. Model:
involved :: Person -> Bool
involved Mike = True
involved Abby = True
involved _ = False
lying :: Person -> Bool
lying Sue = True
lying John = True
lying Jill = True
lying _ = False
The nice thing is you can easily get all satisfying solutions as well. Simply run:
*Puzzle> allSat puzzle
... output elided, prints 12 different solutions
All of this is done pretty much instantaneously, so solving time is more or less irrelevant.
Deductions
Note that the above program finds some assignment to the characters that make all the statements true. But it doesn't tell us what's necessarily true, i.e., what we can deduce for sure. The beauty of using an SMT solver with a programming language is that you can program such things with ease. In this case, we want to check if any of the predicates we have is forced. Here's the extra code you need:
deriving instance Enum Person
deriving instance Bounded Person
isForced :: Person -> SBool -> IO (Maybe (Either Person Person))
isForced p chk = do isSatPos <- isSatisfiable $ puzzle >> constrain chk
isSatNeg <- isSatisfiable $ puzzle >> constrain (sNot chk)
case (isSatPos, isSatNeg) of
(True, True) -> return Nothing
(True, False) -> return (Just (Left p))
(False, True) -> return (Just (Right p))
(False, False) -> error "Neither positive nor negative version of the prediate is satisfiable!"
forced :: IO ()
forced = do let persons = [minBound .. maxBound]
forcedLies <- sequence [isForced p (lying p) | p <- persons]
forcedInvolved <- sequence [isForced p (involved p) | p <- persons]
putStrLn "Conclusions:"
putStrLn $ " Definitely lying : " ++ unwords [show p | Just (Left p) <- forcedLies]
putStrLn $ " Definitely NOT lying : " ++ unwords [show p | Just (Right p) <- forcedLies]
putStrLn $ " Definitely involved: " ++ unwords [show p | Just (Left p) <- forcedInvolved]
putStrLn $ " Definitely NOT involved: " ++ unwords [show p | Just (Right p) <- forcedInvolved]
Now, we get:
*Puzzle> forced
Conclusions:
Definitely lying : Jill John
Definitely NOT lying : Joe Mike Abby Cindy
Definitely involved: Mike
Definitely NOT involved: John Joe
which shows us what we can definitely conclude from the given predicates.

Related

Prolog: How to get oldest and youngest in bloodline

Let's say that I have a bloodline of male population Williams and Skywalker families as my knowledge base:
father(phil,tom, williams).
father(tom, bob, williams).
father(bob, robert, williams).
father(robert, steve, williams).
father(anakin, luke, skywalker)
father(luke, finn, skywalker)
father(finn, andrew, skywalker)
father( andrew, charles, skywalker)
Which rule can I use to know the oldest and youngest in bloodline?
For example
?- oldestYoungest(skywalker,X,Y)
should return
X = anakin
Y = charles
This works with your Knowledge Base (KB) looking the way it does now.
youngest(LastName, Son) :-
father(_, Son, LastName),
\+father(Son, _, LastName).
oldest(LastName, Father) :-
father(Father, _, LastName),
\+father(_, Father, LastName).
oldestYoungest(LastName, Oldest, Youngest) :-
youngest(LastName, Youngest),
oldest(LastName, Oldest).
You should note that Prolog variables are upper-case and constants (or facts) are lower-case.
Technically, this answer finds oldest as the person with no father in the KB and the youngest and the person with no son in the KB. It works because your KB is defined that way.

Prolog - Einstein Riddle

I'm trying to solve the Einstein Riddle using Prolog. I'm sorry for my English. The task is:
In the block of flats is 5 flats. (ground floor a 1., 2., 3., 4. floor)
Family Mullerovi have 4 children.
An administrator lives on the middle floor.
Mrs. Meierova pays for her flat 60 crowns less than a doctor on 3. floor.
Family living on the hightest floor have 5 children.
Family Kernovi have 1 child than teacher.
Mr Kaufmann works as a sales representative.
The teacher pays for her flat 1740 crowns.
On the hightest floor janitor lives.
The doctor pays for his flat 1800 crowns.
In the flat, which costs 1760 crowns, arent any children.
On the 2.floor the family have twice more children than family on the 3.floor.
Mr Hanz lives directly above family Kernovi.
In the flat under the janitor live 2 children.
Mullerovi pay for their flat 1770 crowns.
The roof flat is cheaper 10 crowns than then ground floor.
Sales representative pays 30 crowns more than janitor does.
My code looks like, I don't know how to solve problems with hire:
person('Name', 'Job','Children','Hire','Floor').
houses(Hs):-
length(Hs),
member(person(mullerovi,_,4,1770,_),Hs),
member(person(_,administrator,_,_,2),Hs),
member(person(_,doctor,_,1800,_),Hs),
pays_less(person(_,doctor,_,Hire,_),person('Meinova',_,_,Hire-60,_),Hs),
member(person(_,_,5,_,4),Hs),
have_one_children_less(person('Kernovi',_,Children-1,_,_),person(_,teacher,Children,_,_),Hs),
member(person('Kaufmann','Sales representative',_,_,_),Hs),
member(person(_,teacher,_,1740,_),Hs),
member(person(_,janitor,_,_,4),Hs),
member(person(_,_,0,1760,_),Hs),
have_2x_children(
person(_,_,2*Children,_,2),
person(_,_,Children,_,3),Hs),
lives_above(person('Hanz',_,_,_,_),person('Kernovi',_,_,_,_),Hs),
lives_above(person(_,janitor,_,_,_),person(_,_,2,_,_),Hs),
pays_more(
person(_,_,_,Hire+10,4),
person(_,_,_,Hire,'Ground floor'),Hs),
pays_more(
person(_,'Sale representative',_,Hire+30,_),
person(_,janitor,_,Hire,_),Hs).
Thanks for any advices.
"In the block of flats is 5 flats" translates as length(Hs,5).
Then, pays_less( person(_,doctor,_,Hire,_), person('Meinova',_,_,Hire-60,_),Hs) is undefined; it ought to be
.....
member( person(_,doctor,_,Hire,_), Hs),
member( person('Meinova',_,_,Hire2,_), Hs),
.....
Hire2 is Hire-60,
.....
or something like that.
Acquaint yourself with is/2 operator and its preconditions. B=80, A = B-60 succeeds, unifying A with -(80,60). You want B=80, A is B-60 which succeeds and unifies A with 20 (but would fail if B were not yet a numerical expression).
The line Hire2 is Hire-60, should be placed as high as possible in the predicate, for maximal efficiency.

Prolog riddle solving

The statement :
Four couples in all
Attended a costume ball.
2
The lady dressed as a cat
Arrived with her husband Matt.
3
Two couples were already there,
One man dressed like a bear.
4
First to arrive wasn't Vince,
But he got there before the Prince.
5
The witch (not Sue) is married to Chuck,
Who was dressed as Donald Duck.
6
Mary came in after Lou,
Both were there before Sue.
7
The Gipsy arrived before Ann,
Neither is wed to Batman.
8
If Snow White arrived after Tess,
Then how was each couple dressed?
My code is here , but it returns false :
sol(S):-
S=[[1,L1,M1,LD1,MD1],
[2,L2,M2,LD2,MD2],
[3,L3,M3,LD3,MD3],
[4,L4,M4,LD4,MD4]],
member([_,_,matt,cat,_],S),
member([ALR,_,_,_,bear],S),
(ALR =:= 1 ; ALR =:= 2),
not(member([1,_,vince,_,_],S)),
member([VN,_,vince,_,_],S),
member([PS,_,_,_,prince],S),
VN < PS ,
member([_,_,chuck,witch,donald],S),
not(member([_,sue,_,witch,_],S)),
member([MRY,mary,_,_,_],S),
member([LOU,_,lou,_,_],S),
member([SUE,sue,_,_,_],S),
MRY > LOU,
MRY < SUE,
member([GPS,_,_,gipsy,_],S),
member([ANN,ann,_,_,_],S),
GPS < ANN ,
not(member([_,_,_,gipsy,batman],S)),
not(member([_,ann,_,_,batman],S)),
member([SW,_,_,snowwhite,_],S),
member([TS,tess,_,_,_],S),
SW > TS ,
perm([sue,mary,ann,tess],[L1,L2,L3,L4]),
perm([matt,lou,vince,chuck],[M1,M2,M3,M4]),
perm([cat,witch,gipsy,snowwhite],[LD1,LD2,LD3,LD4]),
perm([donald,prince,batman,bear],[MD1,MD2,MD3,MD4]).
takeout(X,[X|R],R).
takeout(X,[F|R],[F|S]) :- takeout(X,R,S).
perm([],[]).
perm([X|Y],Z) :- perm(Y,W), takeout(X,Z,W).
Any solution ?
You should move all your not(...) goals to the very end of the predicate.
not(G) means, "G is impossible to satisfy right now". When tried too early, with many still non-instantiated variables in the lists, it is in fact very often possible to satisfy a goal, and the whole not(...) call will fail right away.
Alternatively, delay the checking of the inequality on a variable until it is instantiated, e.g. in SWI Prolog with freeze/2 (as seen e.g. in this answer).

How to obtain an "indirect implicant" in propositional logic

I am trying to solve a problem in propositional logic that I don't think I have ever seen described anywhere. I am posting it here to see if someone has a hopefully standard solution for it.
Problem: given a propositional satisfiable logic formula F and a proposition p occurring in F, determine whether there is a satisfiable propositional formula phi not containing p such that
phi => (F => p)
and if so, provide such a phi.
For intuition, I would call phi an "indirect implicant of p wrt F", because it needs to imply p without mentioning p. Instead, it mentions other propositions that affect p through F.
Here's an example, where 'france', 'lyon', 'paris' and 'berlin' are all propositions:
F is "paris => france and lyon => france and berlin => not france"
p is "france"
Then a solution phi is paris or lyon, since that implies (F => france)
(Update: actually the precise solution is (paris or lyon) and not berlin because we did not state anywhere that these propositions are mutually exclusive, so paris and berlin (or lyon and berlin) could both be true at the same time and imply a contradiction. In the present of appropriate background knowledge the solution would be simplified to paris or lyon).
It resembles the problem of finding an implicant for the formula (F => p), but it is not the same since a simple implicant can contain p (and in fact the prime implicant is simply p).
Again, I am posting it here in the hope that someone with more experience looks at it and says: "ah, but that's just a variant of problem such and such". That would be ideal as it would allow me to leverage existing algorithms (particularly satisfiability) and concepts.
Also, just for extra information, I am actually trying to solve this for equality logic, that is, propositional logic where propositions are equalities. That's of course more complex, but the propositional case may be a good stepping stone.
Thanks for your time.
Given your example
F is "paris => france and lyon => france and berlin => not france"
p is "france"
Where F has 4 statements:
F1 = paris
F2 = france and lyon
F3 = france and berlin
F4 = not france
F can be decomposed, through simplifying implications =>:
F1-2: "paris => france and lyon" = "(not paris) or (france and lyon)"
F2-3: "france and lyon => france and berlin" = "(not france or not lyon) or (france and berlin)"
F3-4: "france and berlin => not france" = "(not france or not berlin) and (not france)"
And if we forward-chain through F implications, we will be doing reasoning:
Reason(F): not (not (not F1 or F2) or F3) or F4
not (not (not paris or (france and lyon)) or (france and berlin)) or (not france)
So, we have the following solutions:
S1: not france
S2: not (not (not F1 or F2) or F3):
not (not (not paris or (france and lyon)) or (france and berlin))
Next we can evaluate p where:
p: france => france = TRUE
S1 = not france = not TRUE = FALSE ~ not applicable
S2 = not (not (not paris or (france and lyon)) or (france and berlin))
= not (not (not paris or (TRUE and lyon)) or (TRUE and berlin))
= not (not (not paris or lyon) or berlin)
= not ((paris AND not lyon) or berlin)
= not (paris AND not lyon) AND not berlin
= not (paris AND not lyon) AND not berlin
= (not paris OR lyon) AND not berlin
So, for p to be TRUE in F you need these conditions to be TRUE:
pF1 AND pF2:
pF1 = (not paris OR lyon) = (paris,lyon) in { (F,F), (F,T), (T,T) }
pF2 = not berlin => berlin = FALSE
Here's my own solution. I had posted the question hoping to learn of a standard solution, but perhaps there is not one.
Convert F to an equivalent DNF formula (Disjunctive Normal Form), that is, a disjunction of conjunctions F1 or ... or Fn, where each Fi is a conjunctive clause. A conjunctive clause is a conjunction of literals, where a literal is either a proposition or its negation. Conversion of a formula to DNF is a standard procedure.
For each disjunct Fi. It is in one of three forms:
L1 and ... and Lmi and p
L1 and ... and Lmi and not p
L1 and ... and Lmi (p does not occur in it).
Let inputs(Fi) be the conjunction L1 and ... and Lmi, and output(Fi) be true, false, and neutral respectively.
The intuition is that, if Fi were the only disjunct in the DNF of F, then if inputs(Fi) holds we need p to have the truth value output(Fi) (neutral meaning it could go either way) for F to hold.
The catch is, of course, that Fi will typically not be the only disjunct. For a given disjunct Fi without output true, there may be a disjunct Fj with a distinct output such that ìnputs(Fj) and inputs(Fi) is satisfiable, that is, there is an assignment to the inputs of Fi that satisfy Fj as well, and therefore admit p to be false while still satisfying F.
We therefore name the disjuncts with output true G1, ..., Gk and disjuncts with output false or neutral H1, ..., Hl, and define phi to be
(inputs(G1) or ... or inputs(Gk)) and not (inputs(H1) or ... or inputs(Hl))
Then phi is the solution because it does not contain p and implies F => p. It does not contain p because it is formed out of inputs, defined not to contain p. It implies F => p because it satisfies at least one of the inputs(G_) and does not satisfy any of the inputs(H_). This means that, of all the disjuncts in the DNF of F, only the Gi's have a chance of holding true (all their literals but p are already known to be satisfied). Because they all contain p, if F is true then it must be the case that p holds as well.
Let's see how this manages the example given.
The DNF of
paris => france and lyon => france and berlin => not france
is
(not berlin and france) or
(not lyon and not paris and not france)
We therefore have
G1 equal to not berlin and france
H1equals to not lyon and not paris and not france
so
inputs(G1) = not berlin
inputs(H1) = not lyon and not paris
and therefore phi is
not berlin and not (not lyon and not paris)
which is equivalent to
(lyon or paris) and not berlin
The presence of not berlin in the solution is not intuitive. It is there because F admits that more than one of berlin, paris and lyon be true at the same time. So, while requiring that either paris or lyon be true, it also requires not berlin, or otherwise both france and not france would be implied. In the presence of background knowledge stating that at most one variable be true at the same time, the solution would be simply lyon or paris since that would automatically imply not berlin.

Symbolic logic equivalency

Is there any difference between these two statements, given the following language??
Ben likes dogs and either John or Mary likes dogs.
Ben likes dogs and John or Mary likes dogs.
Using:
B: Ben likes dogs.
J: John likes dogs.
M: Mary likes dogs.
I have B & (J V M) for both...
I'm limited to & () V ~ as my symbols
B & ((J & ~M) V (~J & M))
B & (J V M)
You haven't defined what 'either' means. My guess is that 'either' modifies 'or' to exclusive-or, in which case the two statements are different.
I agree with Mr. Garrison. It's been a long time since I took symbolic logic, but I'd suspect "either" as meaning exclusive-or. So:
B & ((J V M) & ~(J & M))
B & (J V M)
See Exclusive or for some transformations.
It's probably not a good idea to entitle this question "Symbolic logical equivalency", since it might compound the potential confusion of terms, as there is a logic connective for equivalency. As the case may be, if Mary likes dogs is a true proposition, and if John likes dogs also is true (and so forth), then since both propositions have the same truth values, they are equivalent: M <-> J. But that's not the real question here - just want to clarify a potential point of confusion.
Rather, the two example sentences above are about and/or...but specifically, about "or". The first sentence is an example of exclusive "or", since the example follows a conjunction and means either/or. Exclusive "or" is: (a v b) & ~(a & b). That translates to A or B, but not both are true. The second sentence is inclusive "or", as the disjunction follows the conjunction and does not suggest that both only one disjunct must be true; rather, it's an inclusive "or", where either or both could be true.
Therefore, here's how to do the two sentences:
b & ((j V m) & ~(j & m))
b & (j V m)
TrueWill's answer is correct, but I am providing more explanation and confirming the fact that TrueWill's answer is correct.

Resources