I am trying to figure out how to do arithmetic expressions in Pushdown Automata ?(PDA) for example L=W|W=An Bm Cn-m
What i am thinking of doing is to push As then pop Bs and then either pop As with C or Bs with C depending what is left. For example aaabbc (pushing aaa then popping with Bs bba and then either pop A with C or B with C depending which one is bigger.
For a word w to be in the language, it has to have n>=m by your definition (otherwise C^(n-m) is negative, and that's impossible).
So, your automaton basically needs to:
Push to stack when seeing 'a'
pop from stack upon seeing 'b'
pop from stack upon seeing 'c'.
Also, some important issues:
You need to move between different states when seeing a 'new'
character.
Your automaton should accept w=eps (empty word).
w=a^b b^n is also in the language, make sure you take care of that.
I hope I gave you good enough leads to solve it on your own..
Good luck!
Related
I am trying to understand some ancient code from a DEC PDP10 written in BCPL. A sample of the code is as follows:
test scanner()=S.DOTNAME then
$( word1:=checklook.up(scan.info,S.SFUNC,"unknown Special function [:s]")
D7 of temp:=P1 of word1
scanner()
$) or D7 of temp:=SF.ACTION
What do the "D7 of temp" and "P1 of word1" constructs do in this case?
The unstoppable Martin Richards is continuing to add features to the BCPL language(a), despite the fact that so few people are aware of it(b). Only seven or so questions are tagged bcpl on Stack Overflow but don't get me wrong: I liked this language and I have fond memories of using it back in the '80s.
Some of the things added since the last time I used it are the sub-field operators SLCT and OF. As per the manual on Martin's own site:
An expression of the form K OF E accesses a field of consecutive bits in memory. K must be a manifest constant equal to SLCT length:shift:offset and E must yield a pointer, p say.
The field is contained entirely in the word at position p + offset. It has a bit length of length and is shift bits from the right hand end of the word. A length of zero is interpreted as the longest length possible consistent with shift and the word length of the implementation.
Hence it's a more fine-grained way of accessing parts of memory than just the ! "dereference entire word" operator in that it allows you to get at specific bits within a word.
(a) Including, apparently, a version for the Raspberry PI, which may finally give me an excuse to break out all those spare PIs I have lying around, and educate the kids about the "good old days".
(b) It was used for at least one MC6809 embedded system I worked on, and formed a non-trivial part of AmigaDOS many moons ago.
Here is a section of Prolog code defining numeral in a recursive way:
numeral(0).
numeral(succ(X)) :- numeral(X).
When given query numeral(X). Prolog will return:
X = 0 ;
X = succ(0) ;
X = succ(succ(0)) ;
X = succ(succ(succ(0))) ;
X = succ(succ(succ(succ(0)))) ;
X = succ(succ(succ(succ(succ(0))))) ;
X = succ(succ(succ(succ(succ(succ(0)))))) ;
X = succ(succ(succ(succ(succ(succ(succ(0))))))) ;
X = succ(succ(succ(succ(succ(succ(succ(succ(0))))))))
yes
Based on what I have learned, when doing the query, prolog will firstly make X into a variable like (_G42), then it will search the facts and rules to find the match.
In this case, it will find 0 (fact) as a right match. Then it will also try to match the rule. That is considering _G42 is not 0, and _G42 is the succ of another number. Thus, another variable is generated(like _G44), _G44 will match 0 and will also go further like _G42. Since _G44 matches 0, then it will go backward to _G42, getting _G42 = succ(_G44) = succ(0).
I am not sure if I am right about the understanding. I made a diagram to show my comprehension on this problem.
If the analysis is correct, I still feel difficult to design the recursive function like this. Since I am new to Prolog, I want to know if this kind of definition always used in application (say building an expert system, verifying protocols) or it is just for beginners to better understanding the basic searching procedure? If it is often used, what is the key point to design this kind of recursive definition?
My personal opinion: Especially as a beginner, you have zero chance to"understand the recursive search in Prolog". Countless beginners are trying to understand Prolog in this way, and they very consistently fail.
The sad part is that this hits hardest workers the hardest: You always think you can somehow understand it, but in the end, you cannot, because there are too many ways to invoke even the simplest predicates, with uninstantiated and (partly) instantiated arguments, and even with aliased variables.
Your graph nicely illustrates that such a procedural reading gets extremely unwieldy very quickly for even the simplest conceivable recursive definitions.
A much more tractable approach for understanding the predicate is to read it declaratively:
0 is a numeral
If X is a numeral (whatever X is!), then succ(X) of X is also a numeral.
Note that :- even means ←, i.e., an implication from right to left.
My recommendation is to focus on a clear declarative description of what ought to hold. To overcome the initial barriers with Prolog, you must let go the idea that you can trace the steps that the CPU performs in the extreme detail in which you are currently trying to follow it. Prolog is too high-level to be amenable to tracing in this low-level way. It is like trying to interpret between French and English by tracing only the neuronal activities of the speakers.
Write a clear definition and then leave the search to Prolog. There are many other and working ways to understand and break down declarative definitions without getting swamped in low-level details. See for example program-slicing and failure-slicing. They work as long as you stay in the so-called pure monotonic subset of Prolog. Focus on this area, and you will be able to make very fast progress.
Often we would like to refactor a context-free grammar to remove left-recursion. There are numerous algorithms to implement such a transformation; for example here or here.
Such algorithms will restructure a grammar regardless of the presence of left-recursion. This has negative side-effects, such as producing different parse trees from the original grammar, possibly with different associativity. Ideally a grammar would only be transformed if it was absolutely necessary.
Is there an algorithm or tool to identify the presence of left recursion within a grammar? Ideally this might also classify subsets of production rules which contain left recursion.
There is a standard algorithm for identifying nullable non-terminals, which runs in time linear in the size of the grammar (see below). Once you've done that, you can construct the relation A potentially-starts-with B over all non-terminals A, B. (In fact, it's more normal to construct that relationship over all grammatical symbols, since it is also used to construct FIRST sets, but in this case we only need the projection onto non-terminals.)
Having done that, left-recursive non-terminals are all A such that A potentially-starts-with+ A, where potentially-starts-with+ is:
potentially-starts-with ∘ potentially-starts-with*
You can use any transitive closure algorithm to compute that relation.
For reference, to detect nullable non-terminals.
Remove all useless symbols.
Attach a pointer to every production, initially at the first position.
Put all the productions into a workqueue.
While possible, find a production to which one of the following applies:
If the left-hand-side of the production has been marked as an ε-non-terminal, discard the production.
If the token immediately to the right of the pointer is a terminal, discard the production.
If there is no token immediately to the right of the pointer (i.e., the pointer is at the end) mark the left-hand-side of the production as an ε-non-terminal and discard the production.
If the token immediately to the right of the pointer is a non-terminal which has been marked as an ε-non-terminal, advance the pointer one token to the right and return the production to the workqueue.
Once it is no longer possible to select a production from the work queue, all ε-non-terminals have been identified.
Just for fun, a trivial modification of the above algorithm can be used to do step 1. I'll leave it as an exercise (it's also an exercise in the dragon book). Also left as an exercise is the way to make sure the above algorithm executes in linear time.
I have a homework assignment, and i am finished other then one question (see title)
For the life of my, i cannot figure this out... so i started to think it was a trick question.
the current answer that i will submit is:
L1 = {a^n b^n: n>=1} is deterministic. And the reverse,
L2 = {b^n a^n: n>=1} is also deterministic.
However, since all deterministic languages are a subset of Non-deterministic languages, L2 can be considered non-deterministic.
On a side note, the only other example i was trying to make work is:
L3= {{a,b}a}
This seems possible because forward there is non-determinism, since the input could be either a, or b as long as its followed by an a.
and in reverse there is determinism since it will accept only an 'a'. But, it introduces new non-determinism since the second input could be either a or b.
any help / guidance would be great.
I know the deadline has passed, but somebody might find this useful in the future.
(a+b+c)*WcW^R, where W is in (a+b)+; this is non-deterministic because you don't know where the "WcW" bit starts.
W^RcW(a+b+c)*, where W is in (a+b)+; this is deterministic because you can write a deterministic PDA to accept simple palindromes of the form "W^RcW" and modify the accepting state to loop to itself on any of a, b and c.
The trick here is that PDAs have to read input from left to right.
After some google search I find it!
Prefix to Infix
This algorithm is a non-tail recursive method.
The reversed input string is completely pushed into a stack.
prefixToInfix(stack)
1) IF stack is not empty
a. Temp -->pop the stack
b. IF temp is a operator
i. Write a opening parenthesis to output
ii. prefixToInfix(stack)
iii. Write temp to output
iv. prefixToInfix(stack)
v. Write a closing parenthesis to output
c. ELSE IF temp is a space -->prefixToInfix(stack)
d. ELSE
i. Write temp to output
ii. IF stack.top NOT EQUAL to space -->prefixToInfix(stack)
when the Stack top is
F(ABC)
and we enter the algorithm, "A" is written to the output as it was currently the value of
temp=A (say)
Now how I get '-' on the output column as according to the algorithm the next temp value will be "B" which was popped from the stack after the last recursive call.
How the diagram is showing output "((A-" ...
Where I am doing the incorrect assumption ?
Could someone take the trouble in explaining it ?
I don't quite understand your question.
If your stack is ABC, F(ABC) pops the A, goes into branch d.i. and writes an A to output, goes on into d.ii. and performs F(BC), which will, in the end, write both the B and C to output.
If you want your output to look like it does on the diagram, you'll need your stack to be * - A B C (note the spaces between every element!).
Edit:
(As an aside: all this is easier stepped through than described, so I suggest you write the algorithm as a program and start it in your choice of debugger.)
OK, so you have stored the first * in temp (a), written a ( (b.i.), and called the algorithm with the remaining stack (b.ii.). This throws away a blank, then you store a - in the next branch's temp, write a (, and called the algorithm with the remaining stack. At some point, you end up in d.ii., you have just written an A to output, giving you
((A
and the remaining stack is
_B_C
with a space on top and another space between B and C.
So now d.ii. finds the space and doesn't do anything anymore: this control branch is done, and we go back to where we came from, which was d.ii. in your - control branch. You write the - to output at d.iii., call the algorithm with the remaining stack (_B_C) at d.iv., and there you go, writing the B, a ), the * and C and the last ).
Just remember where you came from, so you know where to jump back after your current recursion is done.