diff --git a/level-4/fundamentals-of-computer-science/student-notes/fabio-lama/README.md b/level-4/fundamentals-of-computer-science/student-notes/fabio-lama/README.md new file mode 100644 index 00000000..67f5ae73 --- /dev/null +++ b/level-4/fundamentals-of-computer-science/student-notes/fabio-lama/README.md @@ -0,0 +1,76 @@ +# About + +Listed here is a collection of cheatsheet by topic. Those cheatsheets do not +explain the topics in depth, but rather serve as quick lookup documents. +Therefore, the course material provided by the lecturer should still be studied +and understood. Not everything that is tested at the mid-terms or final exams is +covered and the Author does not guarantee that the cheatsheets are free of +errors. + +* [(First-order) Predicate & Propositional Logic](./cheatsheet_predicate_propositional_logic.pdf) +* [Proofs](./cheatsheet_proofs.pdf) +* [Permutations & Combinatorics](/level-4/computational-mathematics/student-notes/fabio-lama/cheatsheet_probability_combinatorics.pdf) + * (covered in the Authors _Computational Mathematics_ module notes). +* [Automata Theory](./cheatsheet_automata_theory.pdf) +* [Formal Languages & Regular Expressions](./cheatsheet_formal_languages_regular_expressions.pdf) +* [Context-Free Languages](./cheatsheet_context_free_languages.pdf) +* [Turing Machines](./cheatsheet_turing_machines.pdf) +* [Recursion](./cheatsheet_recursion.pdf) + * NOTE: some topics discussed in the _Algorithms I/II_ weeks were + skipped given that those were somewhat redundant with the _Algorithms and + Data Structures I_ module. Some of the algorithms are worth it to be studied + independently, however, such as the Gale-Shapely algorithm for stable + matching, etc. +* NOTE: Complexity theory is not covered by the cheatsheets. + +# Building + +_NOTE_: This step is only necessary if you chose to modify the base documents. + +The base documents are written in [AsciiDoc](https://asciidoc.org/) and can be +found in the `src/` directory. + +The following dependencies must be installed (Ubuntu): + +```console +$ apt install -y ruby-dev wkhtmltopdf +$ gem install asciidoctor +$ chmod +x build.sh +``` + +To build the documents (PDF version): + +```console +$ ./build.sh pdf +``` + +Optionally, for the HTML version: + +```console +$ ./build.sh html +``` + +and for the PNG version: + +```console +$ ./build.sh png +``` + +The generated output can be deleted with `./build.sh clean`. + +# Disclaimer + +The Presented Documents ("cheatsheets") by the Author ("Fabio Lama") are +summaries of specific topics. The term "cheatsheet" implies that the Presented +Documents are intended to be used as learning aids or as references for +practicing and does not imply that the Presented Documents should be used for +inappropriate practices during exams such as cheating or other offenses. + +The Presented Documents are heavily based on the learning material provided by +the University of London, respectively the VLeBooks Collection database in the +Online Library. + +The Presented Documents may incorporate direct or indirect definitions, +examples, descriptions, graphs, sentences and/or other content used in those +provided materials. **At no point does the Author present the work or ideas +incorporated in the Presented Documents as their own.** diff --git a/level-4/fundamentals-of-computer-science/student-notes/fabio-lama/build.sh b/level-4/fundamentals-of-computer-science/student-notes/fabio-lama/build.sh new file mode 100755 index 00000000..309f406f --- /dev/null +++ b/level-4/fundamentals-of-computer-science/student-notes/fabio-lama/build.sh @@ -0,0 +1,77 @@ +#!/bin/bash + +# Because `make` sucks. + +gen_html() { + # Remove suffix and prefix + FILE=$1 + OUT=${FILE%.adoc} + HTML_OUT="cheatsheet_${OUT}.html" + + asciidoctor $FILE -o ${HTML_OUT} +} + +# Change directory to src/ in order to have images included correctly. +cd "$(dirname "$0")/src/" + +case $1 in + html) + for FILE in *.adoc + do + # Generate HTML file. + gen_html ${FILE} + done + + # Move up from src/ + mv *.html ../ + ;; + pdf) + for FILE in *.adoc + do + # Generate HTML file. + gen_html ${FILE} + + # Convert HTML to PNG. + PDF_OUT="cheatsheet_${OUT}.pdf" + wkhtmltopdf \ + --enable-local-file-access \ + --javascript-delay 2000\ + $HTML_OUT $PDF_OUT + done + + # Move up from src/ + mv *.pdf ../ + + # Cleanup temporarily generated HTML files. + rm *.html > /dev/null 2>&1 + ;; + png | img) + for FILE in *.adoc + do + # Generate HTML file. + gen_html ${FILE} + + # Convert HTML to PNG. + IMG_OUT="cheatsheet_${OUT}.png" + wkhtmltopdf \ + --enable-local-file-access \ + --javascript-delay 2000\ + $HTML_OUT $IMG_OUT + done + + # Move up from src/ + mv *.png ../ + + # Cleanup temporarily generated HTML files. + rm *.html > /dev/null 2>&1 + ;; + clean) + rm *.html > /dev/null 2>&1 + rm *.png > /dev/null 2>&1 + rm ../*.html > /dev/null 2>&1 + rm ../*.png > /dev/null 2>&1 + ;; + *) + echo "Unrecognized command" + ;; +esac \ No newline at end of file diff --git a/level-4/fundamentals-of-computer-science/student-notes/fabio-lama/cheatsheet_automata_theory.pdf b/level-4/fundamentals-of-computer-science/student-notes/fabio-lama/cheatsheet_automata_theory.pdf new file mode 100644 index 00000000..f85adfd1 Binary files /dev/null and b/level-4/fundamentals-of-computer-science/student-notes/fabio-lama/cheatsheet_automata_theory.pdf differ diff --git a/level-4/fundamentals-of-computer-science/student-notes/fabio-lama/cheatsheet_context_free_languages.pdf b/level-4/fundamentals-of-computer-science/student-notes/fabio-lama/cheatsheet_context_free_languages.pdf new file mode 100644 index 00000000..ad4db702 Binary files /dev/null and b/level-4/fundamentals-of-computer-science/student-notes/fabio-lama/cheatsheet_context_free_languages.pdf differ diff --git a/level-4/fundamentals-of-computer-science/student-notes/fabio-lama/cheatsheet_formal_languages_regular_expressions.pdf b/level-4/fundamentals-of-computer-science/student-notes/fabio-lama/cheatsheet_formal_languages_regular_expressions.pdf new file mode 100644 index 00000000..86e6ffe8 Binary files /dev/null and b/level-4/fundamentals-of-computer-science/student-notes/fabio-lama/cheatsheet_formal_languages_regular_expressions.pdf differ diff --git a/level-4/fundamentals-of-computer-science/student-notes/fabio-lama/cheatsheet_predicate_propositional_logic.pdf b/level-4/fundamentals-of-computer-science/student-notes/fabio-lama/cheatsheet_predicate_propositional_logic.pdf new file mode 100644 index 00000000..01031a42 Binary files /dev/null and b/level-4/fundamentals-of-computer-science/student-notes/fabio-lama/cheatsheet_predicate_propositional_logic.pdf differ diff --git a/level-4/fundamentals-of-computer-science/student-notes/fabio-lama/cheatsheet_proofs.pdf b/level-4/fundamentals-of-computer-science/student-notes/fabio-lama/cheatsheet_proofs.pdf new file mode 100644 index 00000000..1c5bc81e Binary files /dev/null and b/level-4/fundamentals-of-computer-science/student-notes/fabio-lama/cheatsheet_proofs.pdf differ diff --git a/level-4/fundamentals-of-computer-science/student-notes/fabio-lama/cheatsheet_recursion.pdf b/level-4/fundamentals-of-computer-science/student-notes/fabio-lama/cheatsheet_recursion.pdf new file mode 100644 index 00000000..5c1b66af Binary files /dev/null and b/level-4/fundamentals-of-computer-science/student-notes/fabio-lama/cheatsheet_recursion.pdf differ diff --git a/level-4/fundamentals-of-computer-science/student-notes/fabio-lama/cheatsheet_turing_machines.pdf b/level-4/fundamentals-of-computer-science/student-notes/fabio-lama/cheatsheet_turing_machines.pdf new file mode 100644 index 00000000..86f10c5d Binary files /dev/null and b/level-4/fundamentals-of-computer-science/student-notes/fabio-lama/cheatsheet_turing_machines.pdf differ diff --git a/level-4/fundamentals-of-computer-science/student-notes/fabio-lama/src/assets/automaton_example.png b/level-4/fundamentals-of-computer-science/student-notes/fabio-lama/src/assets/automaton_example.png new file mode 100644 index 00000000..b507cb9f Binary files /dev/null and b/level-4/fundamentals-of-computer-science/student-notes/fabio-lama/src/assets/automaton_example.png differ diff --git a/level-4/fundamentals-of-computer-science/student-notes/fabio-lama/src/assets/turing_machine.png b/level-4/fundamentals-of-computer-science/student-notes/fabio-lama/src/assets/turing_machine.png new file mode 100644 index 00000000..9ae496c6 Binary files /dev/null and b/level-4/fundamentals-of-computer-science/student-notes/fabio-lama/src/assets/turing_machine.png differ diff --git a/level-4/fundamentals-of-computer-science/student-notes/fabio-lama/src/assets/turing_machine_example.png b/level-4/fundamentals-of-computer-science/student-notes/fabio-lama/src/assets/turing_machine_example.png new file mode 100644 index 00000000..cafa37da Binary files /dev/null and b/level-4/fundamentals-of-computer-science/student-notes/fabio-lama/src/assets/turing_machine_example.png differ diff --git a/level-4/fundamentals-of-computer-science/student-notes/fabio-lama/src/automata_theory.adoc b/level-4/fundamentals-of-computer-science/student-notes/fabio-lama/src/automata_theory.adoc new file mode 100644 index 00000000..dd6f9c36 --- /dev/null +++ b/level-4/fundamentals-of-computer-science/student-notes/fabio-lama/src/automata_theory.adoc @@ -0,0 +1,91 @@ += Cheatsheet - Automata Theory +Fabio Lama +:description: Module: CM1025 Fundamentals to Computer Science, started 25. October 2022 +:doctype: article +:sectnums: 4 +:stem: + +== Basics of (finite) Automata + +An **alphabet**, stem:[Sigma], is a non-empty set of symbols. + +[stem] +++++ +Sigma = {0, 1} " binary alphabet"\ +Sigma = {a, b, ..., z} " collection of lowercase letters" +++++ + +A **string** or word is a finite sequence of letters drawn from an alphabet. +**Empty strings**, stem:[epsilon], are strings with zero occurrences of letters. +Empty strings can be from any alphabet. + +The **length** of a string stem:[x] is denoted as stem:[|x|]: + +[stem] +++++ +x = '"hello"'\ +|x| = 5 +++++ + +Other string related notations: + +* The set of **all strings** composed from the letters in stem:[Sigma] is denoted +by stem:[Sigma^**]. +* The set of **all non-empty strings** composed from letters +in stem:[Sigma] is denoted by stem:[Sigma^+] +* The set of **all strings of length stem:[k]** composed from letters in stem:[Sigma] is denoted by stem:[Sigma^k]. + +[stem] +++++ +Sigma = {0, 1}\ +Sigma^** = {epsilon, 0, 1, 00, 01, 10, 11, ...}\ +Sigma^+ = {0, 1, 00, 01, 10, 11, ...}\ +Sigma^2 = {00, 01, 10, 11} +++++ + +Note that the size of stem:[Sigma^k] is denoted as stem:[|Sigma|^k]. + +== Automaton + +A **finite automaton** is a simple mathematical machine; it is a representation +of how computations are performed with _limited memory_ space. It is a model of +computation, which consists of a set of states that are connected by +transitions. It has an input and it has an output. + +An automaton stem:[M] is a 5-tuple (stem:[Q, Sigma, delta, q_0, F]) where: + +* stem:[Q] is a finite set called the **states**. +* stem:[Sigma] is a finite set called **the alphabet**. +* stem:[delta: Q xx E -> Q] is the **transition function**. +* stem:[q_0 in Q] is the **start state**. +* stem:[F sube Q] is the set of **accepted states**. + +.Note: Bottom right is the transition table. D is the only accepted state. +image::assets/automaton_example.png[width=550, align="center"] + +For example, based on the automaton in the picture above: + +* Input stem:[0010] results in state stem:[D]; the input is **accepted** (stem:[D in F]). +* Input stem:[0011] results in state stem:[A]; the input is **rejected** +(stem:[A !in F]). + +=== Language of Automaton + +The set of all strings accepted by an automaton is called the **language** of +that automaton. If stem:[M] is an automaton on alphabet stem:[Sigma], then +stem:[cc L(M)] is the language of stem:[M]: + +[stem] +++++ +cc L(M) = {x in Sigma^** | M " accepts " x} +++++ + +== Determinism + +The difference between Deterministic Finite Automata (DFA) and Nondeterministic +Finite Automata (NFA) is that DFA has exactly one transition and there is a +unique starting state, which is not the case in NFA (hence, +**nondeterministic**). Generally, in NFA there are many choices at one +particular point and an input is accepted if at least one sequence of choices +leads to an accepting state. + diff --git a/level-4/fundamentals-of-computer-science/student-notes/fabio-lama/src/context_free_languages.adoc b/level-4/fundamentals-of-computer-science/student-notes/fabio-lama/src/context_free_languages.adoc new file mode 100644 index 00000000..961a27fc --- /dev/null +++ b/level-4/fundamentals-of-computer-science/student-notes/fabio-lama/src/context_free_languages.adoc @@ -0,0 +1,189 @@ += Cheatsheet - Context-Free Languages +Fabio Lama +:description: Module: CM1025 Fundamentals to Computer Science, started 25. October 2022 +:doctype: article +:sectnums: 4 +:stem: + +== Intro + +Context-free grammar defines a set of rules for connecting strings together, +which is another way of representing languages. It works recursively describing +the structure of the strings. + +== Definition + +A **context-free grammar** is a 4-tuple stem:[(V, Sigma, R, S)] where: + +* **Variables**: a finite set of symbols, denoted stem:[V]. +* **Terminals**: a finite set of letters, denoted by stem:[Sigma], which is +disjoint from stem:[V]. +* **Rules**: a finite set of mappings, denoted by stem:[R], with each rule being +a variable and a string of variables and terminals. +* **Start variable**: a member of stem:[V], denoted by stem:[S]. It is usually +the variable on the left-hand side of the top rule. + +== Generating Strings + +. Start from the **starting symbol**, read its rule. +. Find a **variable** in the rule of the starting symbol and **replace it** with +**a rule** of that variable. +. **Repeat step 2** until there are no variables left. + +A **derivation** is a sequence of substitutions in generating a string. There +may be more than one rule for a variable. Then we can use the "stem:[|]" symbol +to indicate "or". + +For example: + +[stem] +++++ +S -> bSa | ba +++++ + +Respectively: + +[stem] +++++ +S -> bSa\ +S -> ba\ +S => bSa => b baa\ +S => bSa => b bSaa => b b baaa\ +S => bSa => b bSaa => b b bSaaa => b b b baaaa +++++ + +We say stem:[u] **derives** stem:[v], or stem:[u =>^** v] if there is a +derivation from stem:[u] to stem:[v]. + +=== Example + +[stem] +++++ +S -> aS|T\ +T -> b|epsilon +++++ + +== Language of a Grammar + +The language of grammar is all the strings that can be derived from the +starting symbol using the rules of the grammar. + +The formal definition is: + +[stem] +++++ +"If " G = (V, Sigma, R, S) " then " L(G) = {w in Sigma^** | S =>^** w} +++++ + +=== Example + +We have the grammar stem:[G_2]: + +[stem] +++++ +S -> aS|T\ +T -> b|epsilon +++++ + +A few strings in stem:[L(G_2)]: stem:[a, ab, b, epsilon, aa, aab], and **not** +in stem:[L(G_2)]: stem:[ba, ab b, aab b]. + +We define it formally: + +[stem] +++++ +L(G_2) = a^** uu a^** b = {a^i b^j | 0 <= i, 0 <= j <= 1} +++++ + +== Converting from Regular Expressions + +=== Example 1 + +Let's convert stem:[ab^**] to a context-free language: + +* stem:[b^**] can be written as stem:[U -> bU|epsilon] +* stem:[ab^**] can be written as stem:[S -> aU] + +In other words: + +[stem] +++++ +S -> aU\ +U -> bU|epsilon +++++ + +=== Example 2 + +Let's convert stem:[ab^** uu b^**] to a context-free language: + +* stem:[b^**] can be written as stem:[U -> bU|epsilon] +* stem:[ab^**] can be written as stem:[S -> aU] +* stem:[uu] is just an "or", which can be written as stem:[|] + +In other words: + +[stem] +++++ +S -> aU|U\ +U -> bU|epsilon +++++ + +=== Example 3 + +Let's convert stem:[ab^+ uu b^+ b] to a context-free language: + +* stem:[b^+] can be written as stem:[U -> bU|b] +* stem:[ab^+] can be written as stem:[S -> aU] +* stem:[b^+b] can be written as stem:[S -> bU] +* stem:[uu] is just an "or", which can be written as stem:[|] + +In other words: + +[stem] +++++ +S -> aU|bU\ +U -> bU|b +++++ + +=== Example 4 + +Let's convert stem:[Sigma^** a Sigma^**], where stem:[Sigma = {a, b}], to +context-free language: + +* Strings starting with stem:[a], stem:[U -> aX, X in Sigma^**] +* Strings starting with stem:[b], stem:[U -> bX, X in Sigma^**] +* Empty string, stem:[U -> epsilon] + +In other words: + +[stem] +++++ +S -> UaU\ +U -> aU|bU|epsilon +++++ + +=== Example 5 + +Let's convert stem:[Sigma Sigma Sigma^+], a binary string of at least three +in length, to context-free language: + +* stem:[Sigma^+ = (a uu b)^+] which can be written as stem:[U -> aU|bU|a|b] +* stem:[Sigma Sigma^+] can be written as stem:[V -> aU|bU] +* stem:[Sigma Sigma Sigma^+] can be written as stem:[S -> aV|bV] + +In other words: + +[stem] +++++ +S -> aV|bV\ +V -> aU|bU\ +U -> aU|bU|a|b +++++ + +Or, alternatively: + +[stem] +++++ +S -> aaU|abU|baU|b bU\ +U -> aU|bU|a|b +++++ \ No newline at end of file diff --git a/level-4/fundamentals-of-computer-science/student-notes/fabio-lama/src/formal_languages_regular_expressions.adoc b/level-4/fundamentals-of-computer-science/student-notes/fabio-lama/src/formal_languages_regular_expressions.adoc new file mode 100644 index 00000000..6580239c --- /dev/null +++ b/level-4/fundamentals-of-computer-science/student-notes/fabio-lama/src/formal_languages_regular_expressions.adoc @@ -0,0 +1,164 @@ += Cheatsheet - Formal Languages & Regular Expressions +Fabio Lama +:description: Module: CM1025 Fundamentals to Computer Science, started 25. October 2022 +:doctype: article +:sectnums: 4 +:stem: + +NOTE: Make sure to check the _Automata Theory_ cheatsheet, too. + +== Regular Operations + +Let stem:[L_1] and stem:[L_2] be languages. The following operations are regular operations: + +* Union: stem:[L_1 uu L_2 = {x|x in L_1 " or " x in L_2}] +* Concatenation: stem:[L_1 @ L_2 = {xy|x in L_1 " and " y in L_2}] +* Star: stem:[L_1^** = {x_1 x_2 ... x_m | m >= 0, "each " x_1 in L_1}] + +For example: + +[stem] +++++ +A = {a, b, c}\ +B = {x, y, z}\ +A uu B = {a, b, c, x, y, z}\ +A @ B = {ax, ay, az, bx, by, bz, cx, cy, cz}\ +A^** = {epsilon, a, b, c, aa, ab, ac, ba, b b, bc, ca, ...} +++++ + +Where stem:[epsilon] means "none". + +=== Properties + +==== Union + +[stem] +++++ +A uu B = B uu A " (commutative)"\ +(A uu B) uu C = A uu (B uu C) " (associative)"\ +A uu O/ = A\ +A uu A = A " (idempotent)" +++++ + +==== Concatenation + +[stem] +++++ +(A @ B) @ C = A @ (B @ C) " (associative)"\ +A @ epsilon = epsilon @ A = A\ +A @ O/ = O/ +++++ + +_Note that concatenation is not commutative_. + +==== Concatenation and Union + +[stem] +++++ +(A uu B) @ C = (A @ C) uu (B @ C)\ +A @ (B uu C) = (A @ B) uu (A @ C) +++++ + +==== Kleene Star + +[stem] +++++ +O/^** = {epsilon}\ +epsilon^** = epsilon\ +(A^**)^** = A^**\ +A^** @ A^** = A^**\ +(A uu B)^** = (A^** B^**)^** +++++ + +== Regular Expressions + +=== Atomic Expressions + +The empty language, stem:[O/], is a regular expression, which is the empty +regular language. Any letter stem:[a in Sigma] is a regular expression and its +language is stem:[{a}]. Empty string, stem:[epsilon], is a regular expression +representing the regular language stem:[{epsilon}]. + +* _Concatenation_: if stem:[R_1] and stem:[R_2] are regular expressions, so is stem:[R_1 @ R_2]. +* _Union_: if stem:[R_1] and stem:[R_2] are regular expressions, so is stem:[R_1 uu R_2]. +* _Kleene star_: if stem:[R] is a regular expression, so is stem:[R^**]. + +==== Examples + +What is the language of stem:[ab^**]? + +[stem] +++++ +{a, ab, a b b, ab b b, ...} +++++ + +What is the language of stem:[ab^** uu b^**]? + +[stem] +++++ +{a, ab, a b b, a b b b, ... } uu {epsilon, b, b b, b b b, ... } = {epsilon, a, b, ab, b b, a b b, b b b, ...} +++++ + +What is the language of stem:[ab^+ uu b^+b]? + +[stem] +++++ +{ab, a b b, a b b b, ...} uu {b b, b b b, b b b b, ... } = ab^** uu b^** // {a, epsilon, b} " (excluding " a, epsilon, b ")" +++++ + +What is the language of stem:[Sigma^** a]? + +[stem] +++++ +{a, aa, ba, aaa, aba, baa, b b a, ...} +++++ + +What is the language of stem:[Sigma^** a Sigma^**]? + +[stem] +++++ +{a, aa, ab, ba, aaa, aab, aba, a b b, baa, bab, b b a, ...} +++++ + +=== Regular & Non-Regular Languages + +* A language is **regular** if it can be accepted by a **finite automata**. +* A language is **regular** is it can be accepted by a **regular expression**. +* Every finite language is regular. + +Examples of a **non-regular** language: + +[stem] +++++ +L = {a^n b^n | n in NN}\ +L = {x x|x in {a, b}^**}\ +L = {a^(n!) | n in NN} +++++ + +=== Pumping Lemma + +The Pumping Lemma proves whether a language is regular or not. If stem:[L] is a +regular language, then there is a number stem:[p] (the pumping length) where, if +**stem:[s] is any string in stem:[L] of length at least stem:[p]**, then +stem:[s] may be divided into three pieces, stem:[s = xyz], satisfying the +following conditions: + +* stem:[AA i >= 0, xy^i z in L] +* stem:[|y| > 0] +* stem:[|xy| <= p] + +This means that if the language is finite, it is regular, we choose stem:[p] to +be the number of states in the finite automata representing stem:[L] and if +stem:[|s| >= p], stem:[s] must have a repeated state (Pigeonhole Principle). + +For example, let's prove stem:[L = {a^n b^n | n in NN}] is not regular: + +* Assuming stem:[L] is regular. Let stem:[p] be the pumping length. +* Let stem:[s = a^p b^p, |s| > p] +* Pumping Lemma: stem:[s = xyz] +* For any stem:[i, xy^i z in L]. Let us try stem:[i=2] +* Cases: +** 1.) stem:[y] is only stem:[a]'s. stem:[xyyz] will have more stem:[a]'s than stem:[b]'s +** 2.) stem:[y] is only stem:[b]'s. stem:[xyyz] will have more stem:[b]'s than stem:[a]'s +** 3.) stem:[y] has stem:[a]'s and stem:[b]'s. stem:[xyyz] will have stem:[a]'s and stem:[b]'s jumbled up. +* Respectively, stem:[L] is **not** regular. diff --git a/level-4/fundamentals-of-computer-science/student-notes/fabio-lama/src/predicate_propositional_logic.adoc b/level-4/fundamentals-of-computer-science/student-notes/fabio-lama/src/predicate_propositional_logic.adoc new file mode 100644 index 00000000..09afc9bc --- /dev/null +++ b/level-4/fundamentals-of-computer-science/student-notes/fabio-lama/src/predicate_propositional_logic.adoc @@ -0,0 +1,296 @@ += Cheatsheet - (First-order) Predicate & Propositional Logic +Fabio Lama +:description: Module: CM1025 Fundamentals to Computer Science, started 25. October 2022 +:doctype: article +:sectnums: 4 +:stem: + +== Intro + +**Predicates** describe properties of objects. + +For example: + +[stem] +++++ +"odd"(3) +++++ + +stem:["odd"(3)] means stem:[3] is an odd number. stem:["odd"] is a predicate, +stem:[3] is an object. Predicates take arguments and become **propositions**. +A proposition is a statement that can be either _true_ or _false_. It must be +one or the other, and it cannot be both. + +Connectives can be applied: + +[stem] +++++ +"odd"(3) ^^ "prime"(3) +++++ + +This means that stem:[3] is odd but also prime. + +== Syntax + +Propositions are denoted by capital letters, such as stem:[P, Q, ...]. General +statements are denoted by lowercase letters, such as stem:[p, q, ...] + +== Connectives + +**Logical NOT**: stem:[not p] is true if and only if stem:[p] is false (also +called _negation_). + +**Logical OR**: stem:[p vv q] is true if and only if at least one of stem:[p] or +stem:[q] is true or if both stem:[p] and stem:[q] are true (also called +_disjunction_). + +**Logical AND**: stem:[p ^^ q] is true if and only if both stem:[p] and stem:[q] +are true (also called _conjunction_). + +**Logical IF...THEN**: stem:[p -> q] is true if and only if either stem:[p] is +false or stem:[q] is true (also called _conditional_ or _implication_). stem:[p] +is the premise, stem:[q] is the conclusion. + +**Logical IF and only IF**: stem:[p harr q] is true if and only if both stem:[p] +and stem:[q] are true (also called _bi-conditional_). + +**Exclusive OR: XOR**: stem:[p o+ q] is true if stem:[p] or stem:[q] is true but +not both. + +=== Translation to Connectives + +As an example, lets consider the propositions: + +* stem:[P = "I study 20 hours a week"] +* stem:[R = "I will pass the exam"] +* stem:[S = "I will be happy"] +* stem:[Q = "I attend all the lectures"] + +And the following connectives: + +[stem] +++++ +(P vv Q) -> (R ^^ S) +++++ + +which is a translation of: "**If** I study 20 hours a week **or** attend all +the lectures, **then** I will pass the exam **and** I will be happy." + +== Truth Tables + +=== Negation: stem:[not] + +[stem] +++++ +true = not false\ +false = not true +++++ + +=== Conjunction: stem:[^^] + +[stem] +++++ +true ^^ true = true\ +true ^^ false = false\ +false ^^ true = false\ +false ^^ false = false +++++ + +=== Disjunction: stem:[vv] + +[stem] +++++ +true vv true = true\ +true vv false = true\ +false vv true = true\ +false vv false = false +++++ + +=== Implication: stem:[->] + +[stem] +++++ +true -> true = true\ +true -> false = false\ +false -> true = true \ +false -> false = true +++++ + +==== +NOTE: This can seem weird at first, this answer helps: https://math.stackexchange.com/a/100288 + +> If you start out with a false premise, then, as far as implication is +concerned, you are free to conclude anything. (This corresponds to the fact +that, when stem:[p] is false, the implication stem:[p -> q] is true no matter +what stem:[q] is.) + +> If you start out with a true premise, then the implication should be true only +when the conclusion is also true. (This corresponds to the fact that, when +stem:[p] is true, the truth of the implication is the same as the truth of +stem:[q].) +==== + +Additionally, let stem:[p] and stem:[q] be propositions and stem:[A] the conditional statement: + +[stem] +++++ +p -> q +++++ + +then: + +* stem:[p] is called the **hypothesis** (or antecedent or premise) and stem:[q] +is called the **conclusion** (or consequence). +* The proposition stem:[q -> p] is the **converse** of stem:[A]. +* The proposition stem:[not q -> not p] is the **contrapositive** of stem:[A]. + +=== Bi-conditional: stem:[harr] + +[stem] +++++ +1 harr 1 = 1\ +1 harr 0 = 0\ +0 harr 1 = 0\ +0 harr 0 = 1 +++++ + +=== Exclusive or: XOR, stem:[o+] + +[stem] +++++ +1 o+ 1 = 0\ +1 o+ 0 = 1\ +0 o+ 1 = 1\ +0 o+ 0 = 0 +++++ + +== Operator Precedence + +Operators are applied in the following order (ascending): + +. stem:[not] +. stem:[^^] +. stem:[vv] +. stem:[->] +. stem:[harr] + +For example: + +[stem] +++++ +p -> p ^^ not q vv s -= (p -> ((p ^^ (not q)) vv s)) +++++ + +== Descriptors + +A formula that's always true is called a **tautology**. A formula that is true +for at least one scenario is **consistent**. A formula that's never true is +**inconsistent**. A formula can also result in a **contradiction**. + +== Equivalances + +Formulas are equivalanent if they result in the same logical outcomes. + +For example (_De Morgan's Laws_): + +[stem] +++++ +not (p ^^ q) -= not p vv not q\ +not (p vv q) -= not p ^^ not q +++++ + +For example: + +[stem] +++++ +not (true ^^ true) -= false vv false -= false\ +not true vv not true -= not (true ^^ true) = not true = false +++++ + +== Quantifiers + +We use the symbol stem:[EE] to indicate the existence of something +(**existential quantifier**). + +[stem] +++++ +EE x " odd"(x) +++++ + +This means that there exists some stem:[x] that is odd. + +We denote the **universal quantifier** as stem:[AA]. + +[stem] +++++ +AA x ("odd"(x) vv "even"(x)) +++++ + +This meant that **for all** stem:[x] the number is either even or odd. + +Other examples, "All Ps are Qs": + +[stem] +++++ +AA x (P(x) -> Q(x)) +++++ + +And "No Ps are Qs": + +[stem] +++++ +AA x (P(x) -> not Q(x)) +++++ + +=== Quantifiers to Connectives + +stem:[EE x, P(x)] where stem:[x in {x_1, x_2, ..., x_n}] means that there exists +some stem:[x] for which stem:[P(x)] is true. + +Denoted alternatively: + +[stem] +++++ +EE x, P(x) -= P(x_1) vv P(x_2) vv ... vv P(x_3) +++++ + +We can also conclude: + +[stem] +++++ +not EE x, P(x) -= not(P(x_1) vv P(x_2) vv ... vv P(x_3))\ +not EE x, P(x) -= not P(x_1) ^^ not P(x_2) ^^ ... ^^ not P(x_3)\ +not EE x, P(x) -= AA x, not P(x) +++++ + +==== De Morgan's Law for Negation + +[stem] +++++ +not AA x P(x) -= EE x not P(x)\ +not EE P(x) -= AA x not P(x) +++++ + +== Laws of Propositional Logic + +=== Logic 1 + +|=== +||**Disjunction**|**Conjunction** +|idempotent laws|stem:[p vv p -= p]|stem:[p ^^ p -= p] +|commutative laws|stem:[p vv q -= q vv p]|stem:[p ^^ q -= q ^^ p] +|associative laws|stem:[(p vv q) vv r -= p vv (q vv r)]|stem:[(p ^^ q) ^^ r -= p ^^ (q ^^ r)] +|distributive laws|stem:[p vv (q ^^ r) -= (p vv q) ^^ (p vv r)]|stem:[p ^^ (q vv r) -= (p ^^ q) vv (p ^^ r)] +|identity laws|stem:[p vv F -= p]|stem:[p ^^ T -= p] +|domination laws|stem:[p vv T -= T]|stem:[p ^^ F -= F] +|=== + +=== Logic 2 + +|=== +||**Disjunction**|**Conjunction** +|De Morgan's laws|stem:[not (p vv q) -= not p ^^ not q]|stem:[not (p ^^ q) -= not p vv not q] +|absorption laws|stem:[p vv (p ^^ q) -= p]|stem:[p ^^ (p vv q) -= p] +|negation laws|stem:[p vv not p -= T]|stem:[p ^^ not p -= F] +|double negation law|stem:[not not p -= p]| +|=== \ No newline at end of file diff --git a/level-4/fundamentals-of-computer-science/student-notes/fabio-lama/src/proofs.adoc b/level-4/fundamentals-of-computer-science/student-notes/fabio-lama/src/proofs.adoc new file mode 100644 index 00000000..44905b5b --- /dev/null +++ b/level-4/fundamentals-of-computer-science/student-notes/fabio-lama/src/proofs.adoc @@ -0,0 +1,144 @@ += Cheatsheet - Proofs +Fabio Lama +:description: Module: CM1025 Fundamentals to Computer Science, started 25. October 2022 +:doctype: article +:sectnums: 4 +:stem: + +== Intro + +A **proof** is a sequence of logical statements that explain why a statement is +true (or not true). However, some statements are true even if they cannot be +logically proven. + +== Direct Proof + +Direct proofs are easy because no particular technique is used. But it can be +difficult to find a starting point. + +Lets consider the example: + +[stem] +++++ +"even"(n) ^^ "even"(m) -> "even"(n+m) +++++ + +I.e. if both numbers are even, then the sum of both numbers is even, too. + +We can prove this: knowing that when an integer is even, it is twice another +integer. We conclude: + +[stem] +++++ +n = 2k, m = 2l\ +m+n = 2k+2l = 2(k+l) " (factored)"\ +k+l = t " (arbitrary name)"\ +m+n = 2t +++++ + +== Proof by Contradiction (Indirect Proof) + +Lets say we want to prove that a statement is true. We then assume that that +statement is false. Proof by contradiction means we now have to arrive at a +statement that contradicts our assumption (implying that the original statement is +true). + +NOTE: The following example is from Quora: https://qr.ae/pvqpcu + +For example, consider the statement _"there is no largest number in the world"_. +We now assume the opposite: _"stem:[N] is the largest number in the world"_. +What happens if we multiply that number by itself? + +[stem] +++++ +N xx N = N +++++ + +_..._ because we assume stem:[N] is the largest number in the world, meaning +stem:[NxxN] cannot be bigger than stem:[N]. + +We know that when we divide a number by itself, the result is stem:[1]: + +[stem] +++++ +N/N = 1 +++++ + +Respectively: + +[stem] +++++ +(N xx N)/N = (N xx cancel(N))/cancel(N) = N = 1 +++++ + +This implies that the largest number in the world is stem:[1], but we can prove +by contradiction that: + +[stem] +++++ +2 > 1 +++++ + +Hence the original statement _"there is not largest number in the world"_ is correct. + +== Proof by Contrapositive (Indirect Proof) + +Lets say we want to prove the following statement: + +[stem] +++++ +A -> B " is true" +++++ + +The **contrapositive** being: + +[stem] +++++ +A -> B -= not B -> not A +++++ + +Now prove that stem:[not B -> not A] is true. Sometimes it's easier to prove the +contrapositive of a statement. + +NOTE: The following example is from StackExchange: https://math.stackexchange.com/q/88565 + +For example: + +[stem] +++++ +x^2 != x -> x != 1 +++++ + +is equivalent to: + +[stem] +++++ +x = 1 -> x^2 = x +++++ + +Respectively, we can prove: + +[stem] +++++ +1^2 = 1 +++++ + +Hence, the original statement is true. + +== Proof by Induction + +If stem:[P(0)], stem:[P(k)] and stem:[P(k+1)] is true, then stem:[P(n)] is +always true. In other words, if we can prove that the proposition is true for +the first step, the next step and the one after that, then we can conclude that +proposition is always true. + +For example, lets prove that for any positive integer stem:[n], the function +stem:[n^3 + 2n] results in a number divisible by stem:[3]. + +[stem] +++++ +1^3 + 2xx1 = 1 + 2 = 3 -> 3/3 = 1\ +2^3 + 2xx2 = 8 + 4 = 12 -> 12/3 = 4\ +3^3 + 2xx3 = 27 + 6 = 33 -> 33/3 = 11\ +... +++++ diff --git a/level-4/fundamentals-of-computer-science/student-notes/fabio-lama/src/recursion.adoc b/level-4/fundamentals-of-computer-science/student-notes/fabio-lama/src/recursion.adoc new file mode 100644 index 00000000..1c09f317 --- /dev/null +++ b/level-4/fundamentals-of-computer-science/student-notes/fabio-lama/src/recursion.adoc @@ -0,0 +1,102 @@ += Cheatsheet - Recursion +Fabio Lama +:description: Module: CM1025 Fundamentals to Computer Science, started 25. October 2022 +:doctype: article +:sectnums: 4 +:stem: + +== Intro + +When a function calls itself, we refer to this process as "recursion". A +recursive formula can be useful to solve certain kinds of problems. + +=== Example Exercise + +.Disclaimer: The following exercise was solved by ChatGPT and includes direct quotes from its output. +==== +> There are 10 steps and you can take either one step at the time or two steps at +the time. How many ways are there to walk all 10 steps? + +Let stem:[S(n)] be the number of ways to walk stem:[n] steps by taking either one or two steps +at a time. Then: + +[stem] +++++ +S(n) = S(n-1) + S(n-2) +++++ + +The intuition behind this formula is that to walk stem:[n] steps, we can either +take a single step and then walk the remaining stem:[n-1] steps, or take two +steps and then walk the remaining stem:[n-2] steps. Therefore, the total number +of ways to walk stem:[n] steps is the sum of the number of ways to walk +stem:[n-1] steps and the number of ways to walk stem:[n-2] steps. + +We can use this recursive formula to calculate stem:[S(10)]: + +[stem] +++++ +S(1) = 1\ +S(2) = 2\ +S(3) = S(2) + S(1) = 3\ +S(4) = S(3) + S(2) = 5\ +S(5) = S(4) + S(3) = 8\ +...\ +S(10) = 89 +++++ + +NOTE: We define stem:[S(1) = 1] (only one way to walk one step) and stem:[S(2) = 2] +(two ways to walk two steps, either one step at the time or two steps at once). +Therefore, we don't use the recursive formula directly on stem:[S(1)] and +stem:[S(2)]. + +Therefore, there are 89 ways to walk all 10 steps by taking either one or two +steps at a time. +==== + +== Euclid's Algorithm + +Consider the following: there are two non-zero integers stem:[a] and stem:[b], +now lets find the greatest integer that divides stem:[a] and stem:[b] without +leaving a remainder. + +With Euclid's algorithm, lets first assume that stem:[a >= b], then lets +divide stem:[a] by stem:[b] and the remainder is stem:[r]. + +**Importantly**: + +[stem] +++++ +gcd(a, b) = gcd(b, r) = gcd(a, r) +++++ + +By using division once, we have stem:[b <= a, r < b] since the arguments of stem:[gcd] +have decreased. We continue with this until stem:[r = 0], then stem:[b] is the +final stem:[gcd]. + +More formally: + +[stem] +++++ +gcd(a, b) = {(gcd(b, |a mod b|), if b > 0),(a, if b = 0):} +++++ + +For example, if we want to solve stem:[gcd(27, 36)]: + +[stem] +++++ +gcd(27, 36) = gcd(36, 27)\ +gcd(36, 27) = gcd(27, 9)\ +gcd(27, 9) = gcd(9, 0)\ +gcd(9, 0) = 9 +++++ + +Or, if the numbers were reversed: + +[stem] +++++ +gcd(36, 27) = gcd(27, 9)\ +gcd(27, 9) = gcd(9, 0)\ +gcd(9, 0) = 9 +++++ + +Hence, stem:[gcd(27, 36) = gcd(36, 27) = 9]. diff --git a/level-4/fundamentals-of-computer-science/student-notes/fabio-lama/src/turing_machines.adoc b/level-4/fundamentals-of-computer-science/student-notes/fabio-lama/src/turing_machines.adoc new file mode 100644 index 00000000..3250b896 --- /dev/null +++ b/level-4/fundamentals-of-computer-science/student-notes/fabio-lama/src/turing_machines.adoc @@ -0,0 +1,118 @@ += Cheatsheet - Turing Machines +Fabio Lama +:description: Module: CM1025 Fundamentals to Computer Science, started 25. October 2022 +:doctype: article +:sectnums: 4 +:stem: + +NOTE: Make sure to check the _Automata Theory_ cheatsheet, too. + +== Intro + +A **turing machine** is a finite automation with **unbounded random access +memory**. The **finite state automaton** (FSA) provides instructions on an +**infinite tape**, where the input is given and can also be the working space. +Every cell contains one character, but some cells are empty. A **tape head** reads +and writes according to the instructions given by the FSA. + +== Formal Definition + +A turing machine (TM) consists of: + +[stem] +++++ +(Q, Sigma, Gamma, delta, q_1, q_("Acc"), q_("Rej")) +++++ + +where + +* stem:[Gamma] is the tape alphabet that included the blank symbol. +* stem:[Sigma sube Gamma] is the input alphabet. +* stem:[delta: Q xx Gamma -> (Q xx Gamma xx {L, R})] is the transition function. +* stem:[q_1 in Q] is the start state. +* stem:[q_("Acc")] is the accepting state. +* stem:[q_("Rej")] is the rejecting state. + +The **transition function** takes one state and one letter from stem:[Gamma] and +returns a **state** of the automaton, a **letter to be written** on the current +cell of the tape and the **direction** instructing the tape head where to go, +stem:[L] for left, stem:[R] for right. + +.Note that the black box means "blank". +image::assets/turing_machine.png[width=400, align="center"] + +NOTE: Seeing an interactive example makes the behavior of the direction +stem:[{L, R}] clearer. See Week 13, "7.201 Turing machines: examples" and "7.202 +Designing Turing Machines" in the FCS course. + +=== Example + +Given stem:[w in (1 uu 0)^**], make stem:[w in 1^** 0^**]. For example, given +stem:[111001001], make stem:[111110000]. + +image::assets/turing_machine_example.png[width=600, align="center"] + +NOTE: For the interactive process, see Week 14, "7.301 The power of Turing machines". + +== DFA vs TM + +The difference between a Deterministic Finite Automata (DFA) and a Turing +Machine ( TM ) is that a TM **may not terminate** when the input is completely +processed and may process the input **several times**. A TM **always terminate** +at the accepting or rejecting state, while in DFA the process can pass through +those states and continue. Additionally, a TM may **manipulate** the input, may +enter **an infinite loop** and is **deterministic**. + +== The Language of Turing Machines + +The language of a TM is: + +[stem] +++++ +cc L(M) = {w in Sigma^** | M " accepts " w} +++++ + +If stem:[w in cc L(M)], stem:[M] reached accept state. If stem:[w !in cc L(M)], +stem:[M] **does not** reach accept state (either it reaches reject state or +enters an infinite loop). A language is **recognizable** if it is accepted by a +TM, where the TM is called the **recognizer** of stem:[cc L(M)]. + +A TM that does not enter an infinite loop is called a **decider**. The language +is decidable if it is **accepted** by the decider. + +=== Halting Problem + +stem:[RE] ("recursively enumerable") is a class of **all** recognizable +languages stem:[R] is a class of **all** decidable languages. + +Additionally: + +[stem] +++++ +R sube RE +++++ + +In other words, every decider is a recognizer, but not the other way around. The +**halting problem** states that we cannot determine whether an arbitrary TM and +an input will eventually halt or run forever. + + +=== Language Hierarchy + +[stem] +++++ +"RL" sube "CFL" sube R sube RE sube "all languages" +++++ + +where "RL" refers to Regular Languages and "CFL" refers to Context-Free Languages. + +==== Chomsky Hierarchy + +|=== +|Grammar|Languages|Automaton|Example + +|Type-0|Recursively enumerable|Turing machine| +|Type-1|Context-sensitive|Turing machines with bounded tape|stem:[a^nb^nc^n] +|Type-2|Context-free|Push-down|stem:[a^nb^n] +|Type-3|Regular|Finite state|stem:[a^** b^**] +|===