Is statement "No rings are bangles" equivalent to "No bangles are ring" in syllogism? - aptitude

I was solving one question related to Syllogism. But I am not understanding the answer.
Is statement "No rings are bangles" equivalent to "No bangles are rings" in syllogism?
Question:
Statements :
No rings are bangles.
All gold are rings.
Conclusions :
I. No bangles are gold.
II. Some rings are gold.
a) Only conclusion I follows
b) Both conclusions I and II follow
c) Only conclusion II follows
d) Neither conclusion I nor conclusion II follows
e) None of these
Answer: c
As per my opinion answer should be b. Because if "No rings are bangles", to make 1st conclusion false there should be a case exists where at least one Bangle which is a Gold. If B=G exists then, as per statement all golds are rings. It means B=G=R. Which is contradicting the given statement.

A) Only conclusion I follow this is the correct ans

Related

What determines the order in which predicates are run?

I am working with some code that was in part written by my professor that takes a tableau as input, expands it, and then outputs the complete tableau.
I am having trouble understanding the logic behind the order in which the predicates are being run. What is the deciding factor that would, say, make the program address conjunction before negation if both were present in the original formula? And how does recursion play into this?
The code is as follows:
%negation
expand([[not(not(X))|B]|T], T1) :-
expand([[X|B]|T], T1).
%conjunction
expand([[(X)+(Y)|B]|T], T1):-
expand([[X, Y|B]|T], T1).
expand([[not((X)+(Y))|B]|T], T1):-
expand([[not(X)|B], [not(Y)|B]|T], T1).
%disjunction
expand([[(X)/(Y)|B]|T], T1):-
expand([[X|B], [Y|B]|T], T1).
expand([[not((X)/(Y))|B]|T], T1):-
expand([[not(X), not(Y)|B]|T], T1).
%not sure what the rest is or how it works
expand([[X|B]|T1], T5) :-
expand([B], T2), distribute(X,T2,T3), expand(T1,T4), append(T3,T4,T5).
expand([[]|T1], [[]|T2]) :-
expand(T1, T2).
expand([],[]).
distribute(X,[B|T],[[X|B]|T1]) :-
distribute(X,T,T1).
distribute(_,[],[]).
Apologies for the vague post, I am unfamiliar with this language
A Prolog program consists of
Facts, a simple statement of truth. Something like this
mother( jane , alice ) .
mother( jane , john ) .
is two facts that state that Jane is the mother of both Alice and John.
Predicates, more complex assertions of truth. Something like this:
sibling(X,Y) :- same_mother(X,Y), same_father(X,Y) .
half_sibling(X,Y) :- same_mother(X,Y) , \+ same_father(X,Y) .
half_sibling(X,Y) :- \+ same_mother(X,Y) , same_father(X,Y) .
same_mother(X,Y) :- mother(M,X), mother(M,Y) .
same_father(X,Y) :- father(F,X), father(F,Y) .
states that
two people, X and Y, are siblings if they have both the same mother and the same father, and
two people, X and Y, are half-siblings if they have either
the same mother and different fathers, or
different mothers and the same father
Each predicate is a logic proposition written in a restricted form of the predicate calculus, and forms what amounts to a search tree (more of a search graph, really). When you query/execute a predicate, say
sibling(stephen,alice).
Prolog's inference engine essentially traverses the search tree until either succeeds or fails. If it succeeded, one can backtrack into it, and it will continue the traversal until it either succeeds again, or fails.
So, the order in which predicates are "executed" is entirely dependent on the predicate with which evaluation began, and it's structure.
Note that, depending on what arguments/parameters are instantiated or not instantiated, when a predicate is evaluated, allows one to ask questions with more than one answer:
sibling( john, X ). asks the question "Who are John's siblings?"
sibling( X , Y ). asks the question "Who are all the pairs of siblings?"
A good text to start learning Prolog are
Clocksin+Mellish's Programming in Prolog — it's a pretty good introduction to the language.
Clocksin's Clause and Effect — I've heard good things about this as a beginner's text, but I've not read it.
Once you've gotten the basics down...
Sterling+Shapiro's The Art of Prolog is a most excellent book to take you deeper
And O'Keefe's The Craft of Prolog is yet a deeper dive.

prolog in math - searching the level of node in prolog

Assuming here is a binary search tree, and given the rule that above(X,Y) - X is directly above Y. Also I created the rule root(X) - X has no parent.
Then, I was trying to figure out what the depth of node in this tree.
Assume the root node of tree is "r" So I got fact level(r,0). In order to implement the rule level(N,D) :-, what I was thinking is it should be have a recursion here.
Thus, I tried
level(N,D): \+ root(N), above(X,N), D is D+1, level(X,D).
So if N is not a root, there has a node X above N and level D plus one, then recursion. But when I tested this, it just works for the root condition. When I created more facts, such as node "s" is leftchild of node "r", My query is level(s,D). It returns me "no". I traced the query, it shows me
1 1 Call: level(s,_16) ?
1 1 Fail: level(s,_16) ?
I just confusing why it fails when I call level(s,D)?
There are some problems with your query:
In Prolog you cannot write something like D is D+1, because a variable can only be assigned one value;
at the moment you call D is D+1, D is not yet instantiated, so it will probably cause an error; and
You never state (at least not in the visible code) that the level/2 of the root is 0.
A solution is to first state that the level of any root is 0:
level(N,0) :-
root(N).
Now we have to define the inductive case: first we indeed look for a parent using the above/2 predicate. Performing a check that N is no root/1 is not necessary strictly speaking, because it would conflict with the fact that there is an above/2. Next we determine the level of that parent LP and finally we calculate the level of our node by stating that L is LP+1 where L is the level of N and LP the level op P:
level(N,L) :-
above(P,N),
level(P,LP),
L is LP+1.
Or putting it all together:
level(N,0) :-
root(N).
level(N,L) :-
above(P,N),
level(P,LP),
L is LP+1.
Since you did not provide a sample tree, I have no means to test whether this predicate behaves as you expect it to.
About root/1
Note that by writing root/1, you introduce data duplication: you can simply write:
root(R) :-
\+ above(_,R).

How does is_integer(X) procedure work?

I read in Mellish, Clocksin book about Prolog and got to this:
is_integer(0).
is_integer(X) :- is_integer(Y), X is Y + 1.
with the query ?- is_integer(X). the zero output is easy but how does it get 1, 2, 3, 4...
I know it is not easy to explain writing only but I will appreciate any attempt.
After the 1-st result X=0 I hit ; then the query becomes is_integer(0) or is still is_integer(X)?
It's long time I search for a good explanation to this issue. Thanks in advance.
This strikes to the heart of what makes Prolog so interesting and difficult. You're definitely not stupid, it's just extremely different.
There are two rules here. The existence of alternatives causes choice points to be created. You can think of the choice point as a moment when Prolog saw an alternate way of proceeding with the computation. Prolog always tries rules in the order they appear in the database, which will correspond to the order they appear in the source file. So when you issue the query is_integer(X), the first rule matches and unifies X with 0. This is your first result.
When you press ';' you are telling Prolog to fail, that this answer is not acceptable, which triggers backtracking. The only thing for Prolog to do is try entering the other rule, which begins is_integer(Y). Y is a new variable; it may or may not wind up instantiated to the same value as X, so far you haven't seen any reason why that wouldn't be the case.
This call, is_integer(Y) essentially duplicates the computation that's been attempted so far. It will enter the first rule, is_integer(0) and try that. This rule will succeed, Y will be unified with 0 and then X will be unified with Y+1, and the rule will exit having unified X with 1.
When you press ';' again, Prolog will back up to the nearest choice point. This time, the nearest choice point is the call is_integer(Y) within the second rule for is_integer/1. So the depth of the call stack is greater, but we haven't left the second rule. Indeed, each subsequent result will be had by backtracking from the first to the second rule at this location in the previous location's activation of the second rule. I doubt very seriously a verbal explanation like the preceeding is going to help, so please look at this trashy ASCII art of how the call tree is evolving like this:
1 2 2
/ \
1 2
/
1
^ ^ ^
| | |
0 | |
1+0 |
1+(1+0)
where the numbers are indicating which rule is activated and the level is indicating the depth of the call stack. The next several steps will evolve like this:
2 2
\ \
2 2
\ \
2 2
/ \
1 2
/
1
^ ^
| |
1+(1+(1+0)) |
= 3 1+(1+(1+(1+0)))
= 4
Notice that we always produce a value by increasing the stack depth by 1 and reaching the first rule.
The answer of Daniel is very good, I just want to offer another way to look at it.
Take this trivial Prolog definition of natural numbers based on TNT (so 0 is 0, 1 is s(0), 2 is s(s(0)) etc):
n(0). % (1)
n(s(N)) :- n(N). % (2)
The declarative meaning is very clear. (1) says that 0 is a number. (2) says that s(N) is a number if N is a number. When called with a free variable:
?- n(X).
it gives you the expected X = 0 (from (1)), then looks at (2), and goes into a "new" invocation of n/1. In this new invocation, (1) succeeds, the recursive call to n/1 succeeds, and (2) succeeds with X = s(0). Then it looks at (2) of the new invocation, and so on, and so on.
This works by unification in the head of the second clause. Nothing stops you, however, from saying:
n_(0).
n_(S) :- n_(N), S = s(N).
This simply delays the unification of S with s(N) until after n_(N) is evaluated. As nothing happens between evaluating n_(N) and the unification, the result, when called with a free variable, is identical.
Do you see how this is isomorphic to your is_integer/1 predicate?
A word of warning. As pointed out in the comments, this query:
?- n_(0).
as well as the corresponding
?- is_integer(0).
have the annoying property of not terminating (you can call them with any natural number, not only 0). This is because after the first clause has been reached recursively, and the call succeeds, the second clause still gets evaluated. At that point you are "past" the end-of-recursion of the first clause.
n/1 defined above does not suffer from this, as Prolog can recognize by looking at the two clause heads that only one of them can succeed (in other words, the two clauses are mutually exclusive).
I attempted to put into a graphic #daniel's great answer. I found his answer enlightening and could not have figured out what was going on here without his help. I hope that this image helps someone the way that #daniel's answer helped me!

Prolog Recursion - Satisfying Both Directions (Simple)

I am very new to Prolog and I was given this assignment.
My code is as follows:
relatives(cindy,tanya).
relatives(tanya,alan).
relatives(alan,mike).
relatives(kerry,jay).
relatives(jay,alan).
isRelated(X,Y):-
relatives(X,Y).
isRelated(X,Y):-
relatives(X,Z),
isRelated(Z,Y).
Simple enough. This shows that if:
?- isRelated(cindy,mike).
Prolog will return true. Now, I'm stuck on how to make it return true if:
?- isRelated(mike,cindy).
I've been trying to come up with ideas like if isRelated(Z,Y) returns false, then switch X and Y, and run isRelated again. But I'm not sure if Prolog even allows such an idea. Any hints or advice would be greatly appreciated. Thanks!
UPDATE:************************************
So I added:
isRelated(X,Y):-
relatives(X,Y);
relatives(Y,X).
That will satisfy "direct" relationships, but simply enough I found out that it doesn't satisfy indirect relationships.
I really want to do something like, if the initial query:
isRelated(mike,cindy)
fails, then try and see if the reverse is true by switching X and Y:
isRelated(cindy,mike)
That will definitely return true. I just don't know how to do this syntactically in Prolog.
Further hint to those in the comments, as I can't leave comments yet: With your original set of rules and facts,
isRelated(cindy,tanya) is true, but isRelated(tanya,cindy) is not, so you need to make isRelated(X,Y) symmetric; what simple addition to isRelated would achieve that?
Also, you could try drawing a graph of the relation relatives(X,Y), with an arrow from X to Y for all your base facts, and see if that helps you think about how the Prolog interpreter is going to attempt to satisfy a query.
So to answer your last question, you don't switch the values of X and Y in Prolog, like you would call swap(x,y) in C, say. The value held by a logic variable can not be changed explicitly, only back-tracked over. But you can easily use Y where you would use X, and vice versa:
somePred(X,Y):- is_it(X,Y).
somePred(X,Y):- is_it(Y,X).
This defines somePred predicate as a logical disjunction, an "OR". It can be written explicitly too, like
somePred(X,Y):- is_it(X,Y) ; is_it(Y,X).
Note the semicolon there. A comma , between predicates OTOH defines a conjunction, an "AND" (a comma inside a compound term just serves to delimit the term's "arguments").
YOu're almost there, you're just trying, I think, to cram too much stuff into one predicate.
Write the problem statement in English and work from that:
A relationship exists between two people, X and Y
if X and Y are directly related, or
if any direct relative of X, P, is related to Y.
Then it gets easy. I'd approach it like this:
First, you have your set of facts about relatives.
related( cindy, tanya ).
...
related( james, alan ).
Then, a predicate describing a direct relationship is terms of those facts:
directly_related( X , Y ) :- % a direct relationship exists
related(X,Y) % if X is related to Y
. % ... OR ...
directly_related( X , Y ) :- % a direct relationship exists
related(Y,X) % if Y is related to X
. %
Finally, a predicate describing any relationship:
is_related(X,Y) :- % a relationship exists between X and Y
directly_related(X,Y) % if a direct relationship exists between them
. % ... OR ...
is_related(X,Y) :- % a relationship exists between X and Y
directly_related(X,P) , % if a direct relationship exists between X and some other person P
is_related(P,Y) % and [recursively] a relationship exists between P and Y.
. %
The solution is actually more complicated than this:
The facts about relationships describe one or more graphs. More on graphs at http://web.cecs.pdx.edu/~sheard/course/Cs163/Doc/Graphs.html. What you're doing is finding a path from node X to Node Y in the graph.
If the graphs described by the facts about relationships have one or more paths between X and Y, the above solution can (and will) succeed multiple times (on backtracking), once for every such path. The solution needs to be deterministic. Normallly, having established that two people are related, we're done: just because I have two cousins doesn't mean I'm related to my aunt twice.
If the graph of relationships contains cycles (almost certainly true) such that a "circular" path exists: A → B → C → A …, the solution is susceptible to unlimited recursion. That means the solution needs to detect and deal with cycles. How might that be accomplished?

Prolog : Recursion problem with a calculated end condition

I'm trying to model a set of cog wheels in Prolog. And to query to find if two wheels are connected by a chain of others.
I have a simple recursion :
connected(X,Y) :-
engages(X,Y).
connected(X,Y) :-
engages(X,Z),
connected(Z,Y).
If I define engages in terms of a hard-wired predicate :
engages(X,Y) :- touches(X,Y).
and
touches(z1,z2).
touches(z2,z3).
touches(z3,z4).
Then this works.
A test of
connected(z1,z4).
produces true and
connected(z1,z5).
produces false.
However, if I replace my touches predicate with a calculation (that the sum of the two radii is roughly the distance between the two centres), then this search goes into what looks like an infinite recursion (stack overflow) when the answer should be false.
Why should this be, given that my "touches" calculation doesn't itself call the "connected" functor? Is it because a touches functor is going to try to match more atoms than the explicit predicates?
This, roughly, is my calculated touches (A and B are the wheels, ARAD and BRAD are their radii, D is distance and approx is an "approximately equals" function.
touches(A,B) :-
wheel(A,_,_,ARAD),
wheel(B,_,_,BRAD),
distance(A,B,D),
approx(D,(ARAD+BRAD),2),
A \== B.
The infinite recursion occurs because the program doesn't check for cycles. Here's what might happen:
The program finds wheels A and B, that touch.
Given B, it looks for a wheel that touches. It finds A.
Goto 1.
You can prevent this from maintaining a "closed set" of wheels already considered in an extra argument to connected:
connected(X,Y) :-
connected(X,Y,[]).
connected(X,Y,Closed) :-
touches(X,Y),
\+ memberchk(Y,Closed).
connected(X,Z,Closed) :-
touches(X,Y),
\+ memberchk(Y,Closed),
connected(Y,Z,[Y|Closed]).
(Exercise for the reader: shorten this.)

Resources