1. Finite automata and regular languages
Represent a recognizer by the finite information it must remember.
FREE COMPUTER SCIENCE STACK LEVEL · 10 OF 20
Which problems can be solved, and what resources must solving them require?
Which problems can be solved, and what resources must solving them require?
The capabilities and limits of algorithms. This layer connects Automata, Grammars, Decidability, Reductions, P and NP to the rest of the computing stack.
Build formal models of computation, use reductions to compare problems, and distinguish undecidability from computational expense. Every claim needs a language, a model, and an argument.
Which problems can be solved, and what resources must solving them require?
This section is a sequence of worked studies. Each study asks you to reconstruct an example, solve a new problem, and check the assumptions behind your answer. Keep your derivations and code so you can revisit them without looking at the solution.
Represent a recognizer by the finite information it must remember. Construct and trace a deterministic finite automaton. Explain nondeterminism using sets of active states. Distinguish finite memory from unbounded counting.
Explain nested syntax using productions, derivations, and a stack. Derive strings from a context-free grammar. Use stack invariants to recognize balanced delimiters. Distinguish a language from an ambiguous grammar for it.
Distinguish a machine that eventually confirms membership from one that always answers. Describe a Turing-machine configuration and transition. Distinguish decidable and recognizable languages. Explain why simulation requires a fair schedule.
Prove limits by transforming an alleged solver into an impossible one. Reconstruct the halting diagonal argument. State the direction and correctness of a reduction. Distinguish an impossible general solver from useful restricted analyses.
Separate finding a solution from efficiently checking a proposed one. Define P and NP for decision problems. Design and bound a certificate verifier. Explain why input encoding changes complexity claims.
Use reductions to compare problems without overstating what hardness proves. State and prove both directions of a polynomial reduction. Separate NP-hardness from NP-completeness. Interpret worst-case hardness without rejecting useful restricted solutions.
Sets, functions, simple graphs, and basic programming. Each lesson names any additional prerequisites. Revisit the mathematics and programming sections whenever a calculation or execution trace becomes a barrier.
Give a recognizer, a correctness argument, a reduction, and a resource analysis. Identify which model assumptions each conclusion depends on and supply counterexamples to stronger unsupported claims. A correct multiple-choice answer is only one kind of evidence. Preserve the intermediate steps, test an edge case, and explain why an attractive alternative fails.
The primary readings provide fuller treatments and additional exercises. Work the section project after the guided problems, then return to a problem a few days later without notes. Use a failed attempt to identify the specific definition, assumption, or step that needs more practice.
Represent a recognizer by the finite information it must remember.
Explain nested syntax using productions, derivations, and a stack.
Distinguish a machine that eventually confirms membership from one that always answers.
Prove limits by transforming an alleged solver into an impossible one.
Separate finding a solution from efficiently checking a proposed one.
Use reductions to compare problems without overstating what hardness proves.
About 35 minutes. Finite states and induction.
The alphabet is {0,1}. Accept exactly the finite strings containing an even number of ones, including the empty string.
Use two states representing even and odd counts.
Start in accepting state E. On 0, stay in the same state; on 1, switch E and O. The empty string stays E and accepts. 101 visits O,O,E and accepts. 111 visits O,E,O and rejects. Initially the prefix count is zero and even. Reading 0 preserves parity and reading 1 flips it, so induction proves the state invariant for every prefix.
Why can this machine not count an unbounded exact number of ones using the same two states?
Build exact machines and reductions. Every impossibility argument must name the model, the decision question, and the direction of the reduction.
1. Construct and minimize · allow 40 minutes
Construct a DFA over {0,1} accepting strings with an even number of 1s and ending in 0. Include the empty string decision and a complete transition table. Can you merge states? Prove a minimal state count using suffixes that distinguish states. Test all strings of length at most four against a direct specification.
Track parity and whether the last symbol is zero. Some combinations may have identical future behavior even when their histories differ.
Three states suffice: E means even parity but not currently accepting (including the empty string); Z means even parity and last symbol zero; O means odd parity, regardless of the last symbol. Only Z accepts. On 0, E→Z, Z→Z, O→O. On 1, E→O, Z→O, O→E. Odd parity makes the current ending symbol irrelevant: both odd histories reject now and have identical transitions.
All states are reachable: ε reaches E, 0 reaches Z, and 1 reaches O. E and Z are distinguished by the empty suffix, as are O and Z. E and O are distinguished by suffix 0: E reaches accepting Z while O stays rejecting O. Therefore no two of these three reachable states can be merged, and three is minimal. An exhaustive check visits 1+2+4+8+16=31 strings; accept exactly those with positive length, final character 0, and count(1) even. Testing supports the implementation; the state invariant and distinguishing suffixes establish the general claim.
2. Recognize and prove · allow 40 minutes
Design a pushdown recognizer for L={0ⁿ1ⁿ : n≥0}. Explain how it rejects 0101 and 001. Prove L is not regular using the pumping lemma, stating its quantifiers correctly. Does a stack make every decidable language context-free? Give a counterexample with an appropriate qualification.
After the first 1, forbid any further 0. For the pumping proof choose a string only after the alleged pumping length is fixed.
Push one marker per 0. On the first 1, switch permanently to a popping phase and pop one marker per 1. Reject if a 1 needs a marker that is absent, or a 0 appears in the popping phase. Accept at end exactly when no markers remain; accept ε separately. Thus 0101 fails at its second 0, and 001 finishes with a marker left.
Assume a DFA exists. The pumping lemma gives p such that every sufficiently long accepted string has some decomposition xyz with |xy|≤p, |y|>0, and xyⁱz in L for every i≥0. Choose 0ᵖ1ᵖ. Every permitted y consists of one or more 0s. Pumping i=0 leaves fewer 0s than 1s, contradicting membership. The proof works for every permitted decomposition, not just one convenient split. A nondeterministic pushdown automaton with finite control, one stack, and one-way read-only input recognizes exactly the context-free languages. The recognizer for {0ⁿ1ⁿ} above is deterministic, but deterministic pushdown automata recognize a smaller class than all context-free languages. Even the nondeterministic model has a strict restriction: {0ⁿ1ⁿ2ⁿ} is decidable but not context-free. Its non-context-freeness requires a separate argument, such as the context-free pumping lemma; the regular pumping proof above does not prove that stronger result.
3. Reduction and contradiction · allow 45 minutes
Suppose H(P,x) always terminates and correctly decides whether program P terminates on input x. Define D(y) that loops when H(y,y) says halt and terminates otherwise. Analyze D on its own encoding. Then reduce halting to deciding whether a program ever prints READY: construct Q from (P,x) and state both directions. Is the READY property recognizable? Is its complement recognizable?
The construction must be computable without solving halting. A recognizer may run forever on a negative instance.
If H(D,D) predicts termination, D loops by construction. If it predicts looping, D terminates. Both cases contradict correctness, so no such total computable H exists for the general model. This does not say that termination cannot be proved for any particular program or restricted language.
Given P,x, construct Q that simulates P(x) while suppressing its output, then prints READY only after the simulation terminates. This syntactic construction is effective. If P(x) halts, Q prints READY; if P(x) does not halt, Q never reaches the print. A hypothetical READY decider would therefore decide halting. READY is recognizable: simulate the given program and accept when the designated output occurs. Its complement is not recognizable in this model. If both a property and its complement had recognizers, interleaving their steps would eventually obtain acceptance from exactly one and give a total decider. The argument assumes an unbounded abstract machine and a precise output event, not a finite physical machine with a fixed execution deadline.
4. Verify and reduce · allow 50 minutes
For a graph G and integer k, CLIQUE asks whether k mutually adjacent vertices exist. Describe a polynomial-time certificate verifier. Reduce CLIQUE to INDEPENDENT SET using the complement graph, proving both directions. A colleague uses this reduction to claim CLIQUE is hard because INDEPENDENT SET is hard. Identify the logical error. Does a polynomial verifier provide a polynomial algorithm to find a certificate? Explain the status of P versus NP without claiming an unresolved result.
A reduction A≤pB means a solver for B gives a solver for A. To establish B as hard, start from a problem A already known to be hard.
A certificate lists k distinct vertex identifiers. Check that 0≤k≤|V|, identifiers belong to V, no duplicates occur, and every pair has an edge. With an adjacency matrix this uses O(k²) edge tests and polynomial total time; representation construction must also be counted if needed. The complement graph has the same vertices and an edge precisely between distinct vertices not adjacent in G. A set is a clique in G iff it has no pairwise edges in the complement, so it is an independent set of size k there. Building the complement takes O(|V|²) time with this representation.
The displayed reduction establishes that INDEPENDENT SET is at least as hard as CLIQUE. Hardness of the target alone does not establish hardness of the source: an easy problem can reduce to a hard one. Here the complement construction also works in the reverse direction, but that additional argument must be stated. Verification checks a supplied witness; trying all candidate subsets can take exponential time. P⊆NP is known; whether P=NP remains unresolved. NP-completeness combines membership in NP with reductions from all NP problems, often obtained through one already-established NP-complete source.
5 to 7 hours. Create a portfolio connecting machine models, executable recognizers, and proof limits. First implement a generic DFA runner that consumes a JSON transition table and an input string, returning its state trace and acceptance result. Use it for binary strings with an even number of ones that end in zero. Next implement a stack-based checker for properly nested parentheses and brackets, returning either success or the first mismatched closing position plus unmatched opens at end of input. Finally write two short proofs: an argument that a^n b^n is not regular using distinguishable prefixes, and a computable reduction from halting to whether a wrapper program reaches a designated instruction. State exactly which claims are established by finite tests and which require a general argument. Inputs and outputs for both executable tools must be documented, including invalid symbols and malformed machine tables. The reduction is a construction and proof, not an attempt to implement a universal halting solver. Use Python standard-library code and a plain-text or Markdown proof document. Include the empty string in both machine test suites. Explain how the DFA start state determines empty-input acceptance, while the stack checker accepts it because no unmatched delimiter remains.
Add an NFA runner with epsilon transitions and subset construction, then compare NFA and DFA acceptance on an exhaustive bounded input set.