Related
I need to figure out a pushdown automata for constructing strings of the language of both balanced parentheses and brackets, such as this ((([()))])()[]. It seems pretty easy to do for one type of parentheses; your stack consists of ( that you push when you see them, and then you pop one off for each ) you see. However, I'm having trouble figuring it out for the two types of parentheses. Does anyone have any suggestions? Thanks.
You are having trouble because the language you described is not context free (try writing it's context free grammar, it's impossible), because the Pumping Lemma doesn't hold for it.
Intuitively, a PDA can only "remember" one number at all times, while your language requires "remembering" the number of ( and the number of [ previously seen.
There is a subset of your language that is CF, the language of nested and balanced brackets and parentheses.
The CF grammar:
S -> B | P | ε
B -> [B] | [P] | ε
P -> (B) | (P) | ε
And the associated PDA:
when it sees [, pushes b
when it sees (, pushes p
when it sees ), if p is at the top of the stack it pops it, otherwise it rejects the word
when it sees ], if b is at the top of the stack it pops it, otherwise it rejects the word
Disclaimer: this is a school assignment.
New-ish to Prolog and have a decent understanding of the basics. Assignment is to differentiate polynomials. This part is not the problem. I have devised an algorithm that works and implemented it in Prolog to my satisfaction. At this point, calling my diff_term predicate results in a properly differentiated polynomial term every time.
However, when I pass a full polynomial to my diff_poly predicate, whose job it is to parse the terms, pass them for differentiation, and recollect them into a list to return tot he user, things break down. My problem is recursively adding the returned polynomial terms (lists) to the fully-differentiated polynomial (another list). I have consulted numerous related Stackoverflow questions, finding this one particularly useful:
Prolog - recursive list building
I read it thoroughly and re-created the same program in order to understand it. The main difference, however, is that in my situation the values I am adding to the list are being returned by other predicates as opposed to being created within the same predicate as the list is being built in.
The following code consists of my diff_poly predicate, which then calls diff_term. diff_term then calls numerous other homemade predicates to perform the algorithm; however, none of that is an issue, and differentiation, as mentioned above, works well. You can likely understand what my algorithmic approach is by predicate names alone.
The diff_poly predicate is the only diff_poly that exists; there are no base cases or other variations, as I am able to assume (as per assignment specifications) that all input will be consistently and validly formatted. There are, however, a few other diff_term predicates for dealing with variations on term contents, all of which return proper term derivatives.
If I call diff_poly as is, I get 'false' as my return. If I comment out the last line of that predicate and uncomment the one previous to it, I get exactly one differentiated term returned to me, which is expected as their is no recursive call, and proves that the call to/return from diff_term works.
Essentially I just need some direction on how to build the list to be returned. I've tried appending, inserting, etc, but I think the head matching strategy (outlined in the question above) is the way to go, but that I am implementing something incorrectly. Any insight is appreciated.
% differentiates a polynomial with respect to given variable
% polynomials are parsed into terms, and terms are passed to diff_term
diff_poly([Term | Rest], DiffVar, DiffedPoly) :-
diff_term(Term, DiffVar, DiffedTerm),
% DiffedPoly = DiffedTerm.
diff_poly(Rest, DiffVar, [DiffedTerm | DiffedPoly]).
% term is a coefficient and at least one var/exp pair in its member variable list
% term includes occurrence of variable to differentiate with respect to
diff_term([Coef | Rest], DiffVar, Return) :-
flatten(Rest, FlatList),
member(DiffVar, FlatList),
index_of(FlatList, DiffVar, Index),
nth1(Index, FlatList, Exp),
Exp > 1, NewCoef is Coef * Exp, NewExp is Exp - 1,
remove_at(FlatList, Index, RemoveList),
insert_at(NewExp, RemoveList, Index, InsertList),
split_varlist(InsertList, DoneList),
Return = [NewCoef | DoneList], !.
Assuming your diff_term is good (which you can test modularly at the Prolog prompt), let's look at diff_poly:
diff_poly([Term | Rest], DiffVar, DiffedPoly) :-
diff_term(Term, DiffVar, DiffedTerm),
% DiffedPoly = DiffedTerm.
diff_poly(Rest, DiffVar, [DiffedTerm | DiffedPoly]).
This clause says that DiffedPoly is the polynomial [Term|Rest] differentiated with respect to DiffVar. Sounds good so far.
Your first expression within the clause says, *DiffedTerm is Term differentiated with respect to DiffVar. That sounds good, too.
The next commented line says to unify DiffedPoly with DiffedTerm. This would no longer make sense since the fully differentiated polynomial would, in general not be just the differentiated term (unless, of course, the polynomial only had one term). Let's leave that commented out.
Finally, we have:
diff_poly(Rest, DiffVar, [DiffedTerm | DiffedPoly])
This says, The result of differentiating the rest of the polynomial (without the first term) with respect to DiffVar is the first term differentiated with respect to DiffVar (i.e., DiffTerm) followed by the fully differentiated polynomial (DiffedPoly). If you think about that, it doesn't make sense. It's written as if you changed what DiffedPoly really means. This query should be expressing, The fully differentiated polynomial (DiffedPoly) is the differentiation of the initial term (DiffedTerm) followed by the differentiation of the rest of the polynomial (differentiation of Rest with respect to DiffVar). Translate this last description into Prolog, then you'll be almost there.
Almost... that's because there needs to be a base case to the recursion. What happens on an empty polynomial? You would need also to add a diff_poly([], <something>, <something>) for that case.
I think that you should change the 'direction' of information flow, and add a base case.
Something simple like this should work
% we need this one, to match when Rest become an empty list
diff_poly([], _DiffVar, []).
diff_poly([Term | Rest], DiffVar, [DiffedTerm | DiffedPoly]) :-
diff_term(Term, DiffVar, DiffedTerm),
diff_poly(Rest, DiffVar, DiffedPoly).
This list processing pattern can be simplified by maplist/3 introduction
diff_poly(TermList, DiffVar, DiffedList) :-
maplist(diff_poly_(DiffVar), TermList, DiffedList).
% since maplist appends lists'elements to argument list, we need a service predicate
% otherwise, and better, a swap of diff_term arguments could do
diff_poly_(DiffVar, Term, Diffed) :-
diff_term(Term, DiffVar, Diffed).
I want to find theorems. I have read the section on find_theorems in the Isabelle/Isar reference manual:
find_theorems criteria
Retrieves facts from the theory or proof context matching all of given search
criteria. The criterion name: p selects all theorems whose fully qualified
name matches pattern p, which may contain "*" wildcards. The criteria intro,
elim, and dest select theorems that match the current goal as introduction,
elimination or destruction rules, respectively. The criterion solves returns
all rules that would directly solve the current goal. The criterion simp: t
selects all rewrite rules whose left-hand side matches the given term. The
criterion term t selects all theorems that contain the pattern t -- as usual,
patterns may contain occurrences of the dummy "_" , schematic variables, and
type constraints.
Criteria can be preceded by "-" to select theorems that do not match. Note
that giving the empty list of criteria yields all currently known facts. An
optional limit for the number of printed facts may be given; the default is 40.
By default, duplicates are removed from the search result. Use with_dups to
display duplicates.
As far as I understand, find_theorems is used in the find window of Isabelle/jEdit. The above does not help me finding relevant theorems for the following situation (Lambda is a theory of the Nominal Isabelle extension. The tarball is here):
theory First
imports Lambda
begin
theorem "Lam [x].(Lam [y].(App (Var x)(Var y))) = Lam [y].(Lam [x].(App (Var y)(Var x)))"
When I try the search expression Lam Isabelle/jedit says
Inner syntax error: unexpected end of input
Failed to parse term
How can I make it look for all the theorems that contain the constant Lam?
Since Lam like the ordinary lambda (%) is not a term on its own, you should add the remaining parts to get a proper term, which may contain wildcards. In your example, I would perform
find_theorems "Lam [_]. _"
which gives lots of answers.
Typically this happens whenever special syntax was defined for some constant. But there is (almost) always an underlying ("raw") constant. To find out which constant provides the Lam [_]. _ syntax. You can Ctrl-click Lam (inside a proper term) within Isabelle/jEdit. This will jump to the definition of the underlying constant.
For Lam there is the additional complication that the binder syntax uses exactly the same string as the underlying constant, namely Lam, as can be seen at the place of definition:
nominal_datatype lam =
Var "name"
| App "lam" "lam"
| Lam x::"name" l::"lam" binds x in l ("Lam [_]. _" [100, 100] 100)
In such cases you can use the long name of the constant by prefixing it with the theory name, i.e., Lambda.Lam.
Note: The same works for binders like ALL x. P x (with underlying constant All), but not for the built-in %x. x.
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?
Ok, so i have this
edu_less(hs,college).
edu_less(college,masters).
edu_less(masters,phd).
I need to write a function to tell if something is less than the other. The predicate is
edu_le.
So if i put edu_le(hs,phd). it should return yes.
I came up with this.
edu_le(A,B) :- A = B.
edu_le(A,B) :- edu_less(A,B).
edu_le(A,B) :- edu_less(A,C), edu_le(C,B).
I really don't want it to go through everything and return multiple answers.
Is it possible to only return yes or no if it finds that it is in fact less than or equal to the 2nd argument?
So basically if i use the example edu_le(hs,phd) again, then because hs is less than college, and college is than masters, and masters is less than phd, then hs must be less than phd and it would say yes.
Sorry, really new to prolog, still trying to get the hang of this.
In the predicate definition
edu_le(A,B) :- A = B.
edu_le(A,B) :- edu_less(A,B).
edu_le(A,B) :- edu_less(A,C), edu_le(C,B).
the second clause is superfluous and causes repeated generation of answers. Use
edu_le(A,B) :- A = B.
edu_le(A,B) :- edu_less(A,C), edu_le(C,B).
This gives you one true answer, then no more answers (false) on backtracking. You can use a cut in the first clause, but then generating won't work anymore.
?- edu_le(hs,X).
X = hs ;
X = college ;
X = masters ;
X = phd ;
false.
becomes incomplete:
?- edu_le(hs,X).
X = hs.
As mat suggested, use once/1 instead. In a good Prolog implementation, this predicate works as if your program had cuts in strategic places, speeding up your program without disturbing its logical semantics.
The most practical way to write predicates like that is to use the cut (!). The cut causes further clauses not to be considered when backtracking. You would write your predicate as following:
edu_le(A,B) :- A = B, !.
edu_le(A,B) :- edu_less(A,B), !.
edu_le(A,B) :- edu_less(A,C), edu_le(C,B).
The last clause does not need a cut because there are no further clauses to consider anyway. The cut is placed after any tests to determine whether the clause should succeed.
Logic programming purists disapprove of the cut, because it makes the meaning of a predicate depend on the ordering of the clauses, which is unlike logic in mathematics.
!/0 also makes this program incomplete, consider for example the most general query with both versions:
?- edu_le(X, Y).
It is often better to use once/1 if you only want a single proof of a particular goal:
?- once(edu_le(hs, phd)).
I would suggest you NOT to follow the path proposed by Juho Östman and keep purity - otherwise, why should you use Prolog in first instance? If you are too lenient with sticking to the logical paradigm you obtain some unpleasing results. In this case, Juho's predicate is definitely different from yours, and I'll show you why.
First, just drop the useless edu_le(A,B) :- edu_less(A,B). rule, as larsmans suggests. You will obtain a less redundant version of your original predicate:
edu_le1(A, A).
edu_le1(A, B) :- edu_less(A, C), edu_le1(C, B).
It just behaves as edu_le, meaning: given an arbitrary query, it produces exactly the same answer, except for duplicates (edu_le1 has less). You may just be happy with it, but it still has some redundant answers that you may not like; e.g, under SWI:
?- edu_le1(hs, hs)
true ;
false.
Now you may say you do not like it because it still has the redundant false, but if you use Juho's predicate instead (without the useless rule):
edu_le2(A, A) :- !.
edu_le2(A, B) :- edu_less(A, C), edu_le2(C, B).
it's true that you eliminate the useless final false:
?- edu_le2(hs, hs)
true.
?-
but you lose more than that: You lose, as mat remarks, the possibility of generating all the solutions when one variable is not instantiated:
?- edu_le1(hs, B) %same, with more copies, for edu_le
B = hs ;
B = college ;
B = masters ;
B = phd ;
false.
?- edu_le2(hs, B)
B = hs. %bad!
?-
In other words, the latter predicate is NOT equivalent to the former: edu_le and edu_le1 have type edu_le(?A, ?B), while instead edu_le2 has type edu_le2(+A, +B) (see [1] for the meaning). Be sure: edu_le2 is less useful because it does less things, and thus can be reused in less contexts. This because the cut in edu_le2 is a red cut, i.e., a cut that changes the meaning of the predicate where it is introduced. You may nevertheless be content with it, given that you understand the difference between the two. It all depends on what you want to do with it.
If you want to get the best of the two worlds, you need to introduce in edu_le1 a proper green cut that lowers the redundancy when A and B are completely instantiated to terms. At the purpose, you must check that A and B are instantiated to the same term before cutting. You cannot do it with =, because = does not check, but unifies. The right operator is ==:
edu_le3(A, B) :- (A == B -> ! ; true), A = B.
edu_le3(A, B) :- edu_less(A, C), edu_le3(C, B).
Note that the additional cut in the first rule is active only when A and B happen to be the same term. Now that the cut is a proper green cut, the predicate works also in the most general cases as your original one:
?- edu_le3(A, A).
true.
?- edu_le3(A, B). %note that A and B are not the same term
A = B ;
A = hs,
B = college ;
A = hs,
B = masters ;
A = hs,
B = phd ;
A = college,
B = masters ;
A = college,
B = phd ;
A = masters,
B = phd ;
false.
?-
with Prolog backtracking through all the solutions.
I don't think there is some way to eliminate the last false without introducing too strong dependency on edu_lt. This because we must keep open the possibility that there is another edu_lt to explore, in the case you decide later to enrich it with more ground facts. So, in my opinion, this is the best you can have.
[1] SWI Prolog reference manual, section 4.1.