Representing FOL in english language - logic

I have the following FOL formula: ∀e(S(e)) → ∃d(P(d))
And the vocabulary:
variables: e:'exam', d:'day'
functions: S:'successful', P:'party'
I initially translated that formula into:
For every successful exam, there will be a day of party
While apparently the correct translation would be something of the sort of:
You party at least one day after all exams were successful.
Why does the correct one say that we only party after ALL exams were successful?
Does ∀e(S(e)) mean: "For all exams, they will all be successful"?
And ∃d(P(d)) mean: "there exists at least one day where we party"?
And doesn't the implication translte to "if a then b" ?
I think I can somehow see the logic of the correct translation, but there's something about the implication that makes me unsure...

Careful here. This formula:
∀e(S(e)) → ∃d(P(d))
Really only has one precise sense, the one you acknowledge as apparently correct:
If all exams are successful, then there will be a party.
Your translation is wrong for a subtle but significant reason. Your translation:
For every successful exam, there will be a day of party
Corresponds to this formula:
∀e.∃d(S(e) → P(d))
These formulae are not logically equivalent, that is, the following is not a tautology:
(∀e(S(e)) → ∃d(P(d))) <=> (∀e.∃d(S(e) → P(d)))
To see this, consider what happens when you pass ten exams and fail one exam. The original formula is vacuously true regardless of whether any party is had, since ∀e(S(e)) is not satisfied. However, your statement is only true if you have at least one party, since you did pass at least one exam.

Related

Reporting *why* a query failed in Prolog in a systematic way

I'm looking for an approach, pattern, or built-in feature in Prolog that I can use to return why a set of predicates failed, at least as far as the predicates in the database are concerned. I'm trying to be able to say more than "That is false" when a user poses a query in a system.
For example, let's say I have two predicates. blue/1 is true if something is blue, and dog/1 is true if something is a dog:
blue(X) :- ...
dog(X) :- ...
If I pose the following query to Prolog and foo is a dog, but not blue, Prolog would normally just return "false":
? blue(foo), dog(foo)
false.
What I want is to find out why the conjunction of predicates was not true, even if it is an out of band call such as:
? getReasonForFailure(X)
X = not(blue(foo))
I'm OK if the predicates have to be written in a certain way, I'm just looking for any approaches people have used.
The way I've done this to date, with some success, is by writing the predicates in a stylized way and using some helper predicates to find out the reason after the fact. For example:
blue(X) :-
recordFailureReason(not(blue(X))),
isBlue(X).
And then implementing recordFailureReason/1 such that it always remembers the "reason" that happened deepest in the stack. If a query fails, whatever failure happened the deepest is recorded as the "best" reason for failure. That heuristic works surprisingly well for many cases, but does require careful building of the predicates to work well.
Any ideas? I'm willing to look outside of Prolog if there are predicate logic systems designed for this kind of analysis.
As long as you remain within the pure monotonic subset of Prolog, you may consider generalizations as explanations. To take your example, the following generalizations might be thinkable depending on your precise definition of blue/1 and dog/1.
?- blue(foo), * dog(foo).
false.
In this generalization, the entire goal dog(foo) was removed. The prefix * is actually a predicate defined like :- op(950, fy, *). *(_).
Informally, above can be read as: Not only this query fails, but even this generalized query fails. There is no blue foo at all (provided there is none). But maybe there is a blue foo, but no blue dog at all...
?- blue(_X/*foo*/), dog(_X/*foo*/).
false.
Now we have generalized the program by replacing foo with the new variable _X. In this manner the sharing between the two goals is retained.
There are more such generalizations possible like introducing dif/2.
This technique can be both manually and automatically applied. For more, there is a collection of example sessions. Also see Declarative program development in Prolog with GUPU
Some thoughts:
Why did the logic program fail: The answer to "why" is of course "because there is no variable assignment that fulfills the constraints given by the Prolog program".
This is evidently rather unhelpful, but it is exactly the case of the "blue dog": there are no such thing (at least in the problem you model).
In fact the only acceptable answer to the blue dog problem is obtained when the system goes into full theorem-proving mode and outputs:
blue(X) <=> ~dog(X)
or maybe just
dog(X) => ~blue(X)
or maybe just
blue(X) => ~dog(X)
depending on assumptions. "There is no evidence of blue dogs". Which is true, as that's what the program states. So a "why" in this question is a demand to rewrite the program...
There may not be a good answer: "Why is there no x such that x² < 0" is ill-posed and may have as answer "just because" or "because you are restricting yourself to the reals" or "because that 0 in the equation is just wrong" ... so it depends very much.
To make a "why" more helpful, you will have to qualify this "why" somehow. which may be done by structuring the program and extending the query so that additional information collecting during proof tree construction is bubbling up, but you will have to decide beforehand what information that is:
query(Sought, [Info1, Info2, Info3])
And this query will always succeed (for query/2, "success" no longer means "success in finding a solution to the modeled problem" but "success in finishing the computation"),
Variable Sought will be the reified answer of the actual query you want answered, i.e. one of the atoms true or false (and maybe unknown if you have had enough with two-valued logic) and Info1, Info2, Info3 will be additional details to help you answer a why something something in case Sought is false.
Note that much of the time, the desire to ask "why" is down to the mix-up between the two distinct failures: "failure in finding a solution to the modeled problem" and "failure in finishing the computation". For example, you want to apply maplist/3 to two lists and expect this to work but erroneously the two lists are of different length: You will get false - but it will be a false from computation (in this case, due to a bug), not a false from modeling. Being heavy-handed with assertion/1 may help here, but this is ugly in its own way.
In fact, compare with imperative or functional languages w/o logic programming parts: In the event of failure (maybe an exception?), what would be a corresponding "why"? It is unclear.
Addendum
This is a great question but the more I reflect on it, the more I think it can only be answer in a task-specific way: You must structure your logic program to be why-able, and you must decide what kind of information why should actually return. It will be something task-specific: something about missing information, "if only this or that were true" indications, where "this or that" are chosen from a dedicates set of predicates. This is of course expected, as there is no general way to make imperative or functional programs explain their results (or lack thereof) either.
I have looked a bit for papers on this (including IEEE Xplore and ACM Library), and have just found:
Reasoning about Explanations for Negative Query Answers in DL-Lite which is actually for Description Logics and uses abductive reasoning.
WhyNot: Debugging Failed Queries in Large Knowledge Bases which discusses a tool for Cyc.
I also took a random look at the documentation for Flora-2 but they basically seem to say "use the debugger". But debugging is just debugging, not explaining.
There must be more.

About definiteness of definition of algorithm?

I'm reading a note about the definition of algorithm, it has two requirements that I don't know what's the differences between them
Definiteness: Every instruction should be clear and unambiguous. (I found a source with exactly the same statement)
From the resource I have there are 5 requirements: Input, Output, Definiteness, Finiteness, Effectiveness. I can understand the other 4 except the Definiteness. Can anyone provide some better definition if the above is not precise?
From the above I only suspect that there are at least two subtleties should be considered...
For conclusion from answers below: definiteness = defined(clear) + only_one(unambiguous).
Algorithm should be clear and unambiguous. Each of its steps (or phases), and their inputs/outputs should be clear and must lead to only one meaning.
For example, if one step is to add two integers, we must define both “integers” as well as the “add” operation: we cannot for example use the same symbol to mean addition in one place and multiplication somewhere else.
If presented to an educated human, the text should allow him to simulate execution by hand in exactly the way you had in mind (same steps taken, same results obtained).
When you don't quite understand the definition of a term provided by some author, it's often helpful to look for other definitions of it. I especially like the one for "definite" from wiktionary.org:
Free from any doubt.
In this context, clear becomes understandable, and unambiguous becomes with a single meaning.
It just means that instructions in an algorithm should have one and only one interpretation. Moreover, the interpretation should be obvious.
A statement like "Repeat steps 1 to 4 a few times" does not fit the criteria as "few times" can mean different number of tries to different people.
On the other hand, a statement like "Repeat steps 1 to 4 until x is equal to y" where x and y are some parameters in the algorithm is indeed clear and unambiguous.

Prolog River Crossing

So I was given an assignment to try to solve this problem in Prolog, though the teacher has only covered the basics and this is essentially the only project in Prolog. I feel like I'm over thinking it and that he's just expecting too much as a first time Prolog program.
The problem is listed below, how should I go about solving this?
Write a Prolog program that solves the word problem below. As part of the solution, it should print all the crossings, with the paddler listed first.
Tom, Jack, Bill, and Jim had to cross a river using a canoe that held only two people.
In each of the three crossings from the left to the right bank of the river, the canoe had two persons, and in each of the two crossings from the right to the left bank, the canoe had one person. Tom was unable to paddle when someone else was in the canoe with him.
Jack was unable to paddle when anyone else but Bill was in the canoe with him. Each person paddled for at least one crossing.
This is what I have so far, though it "works", it doesn't make sure that everyone paddles at least once.
state(tom(Side),jim(Side),jack(Side),bill(Side),c(Side)).
initial(state(tom(l),jim(l),jack(l),bill(l),c(l))).
final(state(tom(r),jim(r),jack(r),bill(r),c(r))).
canoe(P):-P=p.
canoe(P,C):-P=p,C=c.
bad(state(tom(W),jim(X),jack(Y),bill(Z),c(C))):-
C=l,(W=c;X=c;Y=c;Z=c).
move(state(tom(W),jim(X),jack(Y),bill(Z),c(C)),
state(tom(W1),jim(X),jack(Y),bill(Z),c(C1))):-
((canoe(W1),W=r,W=C,C1=m);(canoe(W),W1=l,W1=C1)).
move(state(tom(W),jim(X),jack(Y),bill(Z),c(C)),
state(tom(W),jim(X1),jack(Y),bill(Z),c(C1))):-
((canoe(X1),X=r,X=C,C1=m);(canoe(X),X1=l,X1=C1)).
move(state(tom(W),jim(X),jack(Y),bill(Z),c(C)),
state(tom(W),jim(X),jack(Y1),bill(Z),c(C1))):-
((canoe(Y1),Y=r,Y=C,C1=m);(canoe(Y),Y1=l,Y1=C1)).
move(state(tom(W),jim(X),jack(Y),bill(Z),c(C)),
state(tom(W),jim(X),jack(Y),bill(Z1),c(C1))):-
((canoe(Z1),Z=r,Z=C,C1=m);(canoe(Z),Z1=l,Z1=C1)).
move(state(tom(W),jim(X),jack(Y),bill(Z),c(C)),
state(tom(W1),jim(X1),jack(Y),bill(Z),c(C1))):-
((canoe(X1,W1),W=l,W=X,W=C,C1=m);
(canoe(X,W),W1=r,W1=X1,W1=C1)).
move(state(tom(W),jim(X),jack(Y),bill(Z),c(C)),
state(tom(W1),jim(X),jack(Y),bill(Z1),c(C1))):-
((canoe(Z1,W1),W=l,W=Z,W=C,C1=m);
(canoe(Z,W),W1=r,W1=Z1,W1=C1)).
move(state(tom(W),jim(X),jack(Y),bill(Z),c(C)),
state(tom(W),jim(X1),jack(Y1),bill(Z),c(C1))):-
((canoe(X1,Y1),Y=l,Y=X,Y=C,C1=m);
(canoe(X,Y),Y1=r,Y1=X1,Y1=C1)).
move(state(tom(W),jim(X),jack(Y),bill(Z),c(C)),
state(tom(W),jim(X1),jack(Y),bill(Z1),c(C1))):-
((canoe(Z1,X1);canoe(X1,Z1)),
Z=l,Z=X,Z=C,C1=m);
((canoe(Z,X);canoe(X,Z)),Z1=r,Z1=X1,Z1=C1).
move(state(tom(W),jim(X),jack(Y),bill(Z),c(C)),
state(tom(W),jim(X),jack(Y1),bill(Z1),c(C1))):-
((canoe(Y1,Z1);canoe(Z1,Y1)),
Y=l,Y=Z,Y=C,C1=m);
((canoe(Y,Z);canoe(Z,Y)),Y1=r,Y1=Z1,Y1=C1).
find(Path):-initial(S),rez(S,Path).
bkt(State,Path,[Path|State]):-final(State).
bkt(State,Path,Sol):-move(State,Next),not(bad(Next)),
not(member(Next,Path)),bkt(Next,[Path|Next],Sol).
rez(State,Sol):-bkt(State,[State],Sol).
start:-find(D),writef('%w\n',D).
(This answer may be too late, but since this is quite a classic problem/puzzle which has many many variants, I think it might still be useful to try and break the problem down a little bit.)
As yet stated in answers above, I think it might be a good idea to do some refactoring and try to write a simpler, more manageable model for this problem. What I mean with this is if someone asked you for example to 'quickly modify' your code to integrate let's say a fifth person to the puzzle, it wouldn't be much fun to refactor the code above.
You could start -this is just one approach to give you an idea- by encoding the configuration of the 4 men in a list, where we use an 'l' or 'r' to specify whether someone is located on the left or right side of the river bank. This would give us an initial state like so:
% Tom, Jack, Bill, and Jim are all on the left side
[l,l,l,l]
And we want to reach the goal state:
% Tom, Jack, Bill, and Jim are all on the right side
[r,r,r,r]
This gives us a model that is a lot easier to read/understand (imo).
We could then think some more about how we are going to encode actual transports between the river banks. We wrote our list configuration to specify which person is located where, so now we need a Prolog predicate that can transform one configuration into another. Let's say:
transport(StartState,[Persons],EndState)
Now, for the implementation, instead of explicitly matching on all possible moves (like you do in your current code), it's always a good idea to try and generalise what exactly is happening (the fun part in Prolog :) ).
Without writing too complicated code at once, we break the problem down into small pieces:
% Facts defining a crossing of the river
cross(l,r).
cross(r,l).
% Transport example for Tom
transport([X,Jack,Bill,Jim],[tom],[Y,Jack,Bill,Jim]) :- cross(X,Y).
As you can see, we now defined 'transport' in a very simple way: it is known that Tom will only cross the river on his own, so we use the cross fact to change his location. (Note that Jack, Bill and Jim are just variables stating either an 'l' or 'r' as indication on which river bank those people are located. Since Tom only crosses on his own, these variables will not change!). We could write this even more abstract and don't match specifically on 'tom', but I'm trying to keep it simple in this example.
Of course, we still need to express which crossings are valid and which aren't. From your question: "In each of the three crossings from the left to the right bank of the river, the canoe had two persons, and in each of the two crossings from the right to the left bank, the canoe had one person."
These conditions can very easily be coded using our 'transport' predicate since the initial state (first arg) tells us whether we are crossing from left to right, or vice versa and our 2nd argument specifies a list of which persons are crossing. In other words, the direction of the crossing and the amount of passengers are already known and it seems a bit trivial to write down these conditions here.
Next up: "Jack was unable to paddle when anyone else but Bill was in the canoe with him." Again, this is already very easily written together in our 'transport' (note that I've used wildcards to leave out information we don't care about for this particular condition, but of course, this will probably be different in the resulting end code. It is merely to give an example.):
% Transport example for Jack (Persons length = min 1 - max 2)
transport([_,_,_,_],Persons,[_,_,_,_]) :-
length(Persons,2),
( member(jack,Persons) ->
member(bill,Persons)
;
* other condition(s) *
).
% Alternative with pattern matching on Persons
transport([_,_,_,_],[A,B],[_,_,_,_]) :-
* if jack is A or B, then bill is the other one *
Another quick example: "Tom was unable to paddle when someone else was in the canoe with him."
% Tom cannot peddle in a team of 2
transport([_,_,_,_],Persons,[_,_,_,_]) :-
length(Persons,2),
\+ member(tom,Persons).
As you may have noticed, we have now almost completely broken down the problem in bits and pieces that can be very easily expressed in our model and we are not far from writing the actual solver. There are however enough code examples to be found online and I don't think it's necessary to work out any more of the code right here.
More inspiration can be found by searching for the classic Fox-Goose-Beans/Cabbage puzzle.
Good luck to everyone!

Why don't Standardize variables just violate completeness of resolution

I have been reading some notes on converting first order logic (FOL) sentences to conjunctive normal form (CNF), and then performing resolution.
One of the steps of converting to CNF, is Standardize variables.
I have been searching to find an why complete condition of resolution algorithm violate and soundness doesn't violate, if i don't standardize variables.
anyone could add details why just violate completeness, and soundness is remain?
Here is an example that may help you visualize this. Suppose your theory is
(for all X : nice(X)) or (for all X : smart(X)) (1)
which, if you standardize apart, will result in the CNF:
nice(X) or smart(Y)
that is, everybody in a population is nice, or everybody in a population is smart, or both.
Dropping standardize apart will produce a CNF
nice(X) or smart(X)
which is equivalent to
(for all X : nice(X) or smart(X)) (2)
that is, for each individual in a population, that individual is nice, or smart, or both.
This theory (2) is saying less, it is weaker, than the original theory (1), because it admits a situation in which it is not true that everybody is nice, and it is not true that everybody is smart, but it is true that each individual is one or the other or both. In other words, (2) does not imply (1), but (1) implies (2) (if the whole population is nice, then each individual is nice; if the whole population is smart, then each individual is smart; therefore, each individual is either nice or smart). The set of possible worlds accepted by (2) is strictly larger than the set of possible worlds accepted by (1).
What does this say about completeness and soundness?
Using (2) is not complete because I can show you a counter-example of a true theorem in (1) that is not proven true when using (2). Consider the theorem "If John is not nice but smart, then Liz is smart". This is true given (1) because if the whole population shares one of those two qualities, then it must be "smart" since John is not nice, so Liz (and everyone else) must also be smart. However, given (2) this is not true anymore (it could be that Liz is nice but not smart, and everybody else is one or the other, which still would be ok given (2)). So I can no longer prove a true theorem using (2) (after dropping standardize apart), and therefore my inference is not complete.
Now suppose I prove some theorem T to be true, using (2). This means T holds in every possible world in which (2) holds, including the sub-set of them that hold in (1) (according to the third paragraph above from here). Therefore T is true in (1) as well, so performing inference using (2) is still sound.
In a nutshell: when you do not standardize apart, you "join" statements about entire domains (populations) and make them about individuals, which will be weaker and will not imply some facts that were implied before; they will be lost and your procedure will not be complete.

Validity and satisfiability

I am having problems understanding the difference between validity and satisfiability.
Given the following:
(i) For all F, F is satisfiable or ~F is satisfiable.
(ii) For all F, F is valid or ~F is valid.
How do I prove which is true and which is false?
Statement (i) is true, as for all F, F will either be satisfiable, or ~F will be satisfiable (truth table). However, how do I go about solving for statement (ii)?
Any help is highly appreciated!
Aprilrocks92,
I don't blame you for being confused, because actually logicians, mathematicians, heck even those philosopher types use the words validity differently sometimes.
Trying not to overcomplicate, I'll give you a thin definition: a conclusion if valid when it is true whenever the premises are true. We also say, given a suitably defined logic, that the conclusion follows as a "logical consequence" of the premises.
On the other hand, satisfisability means that there exists a valuation of the non logical symbols in the formula F that makes the formula true in the logic.
So I should probably mention the difference between semantics and syntax to explain. The syntax of your logic is all those logical and non logical symbols, and the deductive rules that enable you to make "steps" towards proof in the logic. My definition of satisfisability above mentioned the word "valuation"- now how does that fit? Well the answer is that you need to supply a semantics: in short this is the structure that the formula of the logic are expressions of, usually given in set theory, and a valuation of a given F is a function that maps all the non logical symbols in F to sets and members of sets, which a given semantics for the logic composes into a truth value.
Hmm. I'm not sure that's the best explanation, but I don't have much time.
Either way, that should help you understand the difference. To answer your question about the difference between (i) and (ii) without giving too much away, think: what's the relationship between the two? Well given that as above an F' is true given a valuation that sends the sentence to true. So you could "rewrite" my definition of validity as: a conclusion is valid iff whenever the premises are satisfisable the conclusion is satisfisable.
Now, with regards your requirement to prove these things, I strongly suspect you've got a lot more context about your logic you're not telling us and your teacher or text book has intimated a context in which to answer these, as actually taken in the general sense your question doesn't make complete sense.

Resources