|
60 | 60 | { |
61 | 61 | "cell_type": "markdown", |
62 | 62 | "metadata": {}, |
63 | | - "source": [] |
| 63 | + "source": [ |
| 64 | + "### The `Expr` class\n", |
| 65 | + "\n", |
| 66 | + "The `Expr` class is the one that enables us to work with propositional logic. This class, combined with the `expr` function will enable us to work with propositional logic with much ease.\n", |
| 67 | + "\n", |
| 68 | + "An instance of the `Expr` class, an `Expr` object represents a symbolic mathematical expression. Truth be told, this class can handle not just Propositional Logic but also First-Order Logic. (As a matter of fact, you can also do arithmetic using this class but you would just be introducing unnecessary complication for a simple task). For the case of our Propositional Logic, an `Expr` object represents a propositional sentence. If you will have a look at its `__init__`, you will see that an `Expr` object just stores the operator and the arguments of a propositional sentence. This is important to note. The `Expr` class does not define the *logic* of Propositional Logic; nor will we be defining it ourselves. It just gives you a way to *represent* expressions. You won't be able to do any propositional math using `Expr`; you won't be be able assign a value of `True` to `P` and `False` to `Q` and then do a `P` ∧ `Q` to get `False`. No, you won't be able to do that. What you will be able to do is to create a representation of sentence and assign it to `P`. Something like,\n", |
| 69 | + "\n", |
| 70 | + "```python\n", |
| 71 | + "sent = Expr(\"==>\", \"A & B\", \"C\")\n", |
| 72 | + "```\n", |
| 73 | + "\n", |
| 74 | + "which is represents the sentence\n", |
| 75 | + "\n", |
| 76 | + "> (A ∧ B) → C\n", |
| 77 | + "\n", |
| 78 | + "That's not much, you say. We can create representations of sentences using strings, you continue. Well, we manipulate the `Expr` objects to convert a sentence to its CNF (`to_cnf`), check satisfiability of a sentence (`dpll_satisfiable`), use resolution to find out if a knowledge base entails a sentence (`pl_resolution`) and whatnot. Best of luck doing that with your string representations!\n", |
| 79 | + "\n", |
| 80 | + "So, the point to take away from the last two paragraphs: The `Expr` class just allows you to create good, easily manipulable representations of propositional sentences. It does a little more than that though. Before I get into that let us create a few expressions of our own to experiment with them later on." |
| 81 | + ] |
| 82 | + }, |
| 83 | + { |
| 84 | + "cell_type": "code", |
| 85 | + "execution_count": 2, |
| 86 | + "metadata": { |
| 87 | + "collapsed": true |
| 88 | + }, |
| 89 | + "outputs": [], |
| 90 | + "source": [ |
| 91 | + "from logic import *\n", |
| 92 | + "\n", |
| 93 | + "P = Expr(\"P\")\n", |
| 94 | + "Q = Expr(\"Q\")\n", |
| 95 | + "R1 = Expr(\"&\", \"A\", \"B\")\n", |
| 96 | + "R2 = Expr(\"==>\", \"C | D\", \"E\")" |
| 97 | + ] |
| 98 | + }, |
| 99 | + { |
| 100 | + "cell_type": "markdown", |
| 101 | + "metadata": {}, |
| 102 | + "source": [ |
| 103 | + "Note here that you can create expressions that have no operators (like the literals `P` and `Q`), simple expressions of literals (like the sentence R1 which represents `A` ∧ `B`) and also expressions that have, as their arguments, complex sentences represented as strings. But, these strings that are allowed as arguments, can use only certain symbols in them. This is the list of symbols that you should use when you want to put complex sentences as arguments to the `Expr` constructor:\n", |
| 104 | + "\n", |
| 105 | + "| Operation | Propositional Symbol | Operator to use in Code |\n", |
| 106 | + "|--------------------------|----------------------|-------------------------|\n", |
| 107 | + "| Negation | ¬ | ~ |\n", |
| 108 | + "| And | ∧ | & |\n", |
| 109 | + "| Or | ∨ | | |\n", |
| 110 | + "| Implies | → | >> or ==> |\n", |
| 111 | + "| Biconditional | ↔ | % or <=> |\n", |
| 112 | + "| **Some additional ones** | | |\n", |
| 113 | + "| Inequality (Xor) | (Dunno) | =/= or ^ |\n", |
| 114 | + "| Reverse Implication | ← | << or <== |\n", |
| 115 | + "\n", |
| 116 | + "Also, this is the precedence sequence with which the operators will be evaluated in code. The highest precedence operators are at the top:\n", |
| 117 | + "\n", |
| 118 | + " ~\n", |
| 119 | + " % <=>\n", |
| 120 | + " << <== >> ==>\n", |
| 121 | + " &\n", |
| 122 | + " ^\n", |
| 123 | + " |\n", |
| 124 | + " \n", |
| 125 | + "Note that the `<=>` and the implication operators are quite at the top. So make sure to use parenthesis correctly when using them with others like `&`, `^` and `|`. You might note that the precedence of these operators is the same as that in Python language. This is not just a coincidence. More about this later.\n", |
| 126 | + "\n", |
| 127 | + "Getting back to the `Expr` class and the expressions that we have created, lets create a more complex expression from the ones we have already created:" |
| 128 | + ] |
| 129 | + }, |
| 130 | + { |
| 131 | + "cell_type": "code", |
| 132 | + "execution_count": 4, |
| 133 | + "metadata": { |
| 134 | + "collapsed": true |
| 135 | + }, |
| 136 | + "outputs": [], |
| 137 | + "source": [ |
| 138 | + "# Cell: Creating complicated sentences\n", |
| 139 | + "R3 = Expr(\"<=>\", R1, Q)\n", |
| 140 | + "R4 = Expr(\"==>\", R2, P & ~Q)" |
| 141 | + ] |
| 142 | + }, |
| 143 | + { |
| 144 | + "cell_type": "markdown", |
| 145 | + "metadata": {}, |
| 146 | + "source": [ |
| 147 | + "So, these are the expressions that we've created now. To display these expressions in a nice, intuitive form, the `__repr__` method has been implemented accordingly. It called when we put the variable in the interpreter or when we use the `print` function. Let's try both:" |
| 148 | + ] |
| 149 | + }, |
| 150 | + { |
| 151 | + "cell_type": "code", |
| 152 | + "execution_count": 6, |
| 153 | + "metadata": { |
| 154 | + "collapsed": false |
| 155 | + }, |
| 156 | + "outputs": [ |
| 157 | + { |
| 158 | + "data": { |
| 159 | + "text/plain": [ |
| 160 | + "P" |
| 161 | + ] |
| 162 | + }, |
| 163 | + "execution_count": 6, |
| 164 | + "metadata": {}, |
| 165 | + "output_type": "execute_result" |
| 166 | + } |
| 167 | + ], |
| 168 | + "source": [ |
| 169 | + "P" |
| 170 | + ] |
| 171 | + }, |
| 172 | + { |
| 173 | + "cell_type": "code", |
| 174 | + "execution_count": 7, |
| 175 | + "metadata": { |
| 176 | + "collapsed": false |
| 177 | + }, |
| 178 | + "outputs": [ |
| 179 | + { |
| 180 | + "data": { |
| 181 | + "text/plain": [ |
| 182 | + "(A & B)" |
| 183 | + ] |
| 184 | + }, |
| 185 | + "execution_count": 7, |
| 186 | + "metadata": {}, |
| 187 | + "output_type": "execute_result" |
| 188 | + } |
| 189 | + ], |
| 190 | + "source": [ |
| 191 | + "R1" |
| 192 | + ] |
| 193 | + }, |
| 194 | + { |
| 195 | + "cell_type": "code", |
| 196 | + "execution_count": 9, |
| 197 | + "metadata": { |
| 198 | + "collapsed": false |
| 199 | + }, |
| 200 | + "outputs": [ |
| 201 | + { |
| 202 | + "data": { |
| 203 | + "text/plain": [ |
| 204 | + "(((C | D) ==> E) ==> (P & ~Q))" |
| 205 | + ] |
| 206 | + }, |
| 207 | + "execution_count": 9, |
| 208 | + "metadata": {}, |
| 209 | + "output_type": "execute_result" |
| 210 | + } |
| 211 | + ], |
| 212 | + "source": [ |
| 213 | + "R4" |
| 214 | + ] |
| 215 | + }, |
| 216 | + { |
| 217 | + "cell_type": "code", |
| 218 | + "execution_count": 10, |
| 219 | + "metadata": { |
| 220 | + "collapsed": false |
| 221 | + }, |
| 222 | + "outputs": [ |
| 223 | + { |
| 224 | + "name": "stdout", |
| 225 | + "output_type": "stream", |
| 226 | + "text": [ |
| 227 | + "P\n", |
| 228 | + "(A & B)\n", |
| 229 | + "(((C | D) ==> E) ==> (P & ~Q))\n" |
| 230 | + ] |
| 231 | + } |
| 232 | + ], |
| 233 | + "source": [ |
| 234 | + "print(P)\n", |
| 235 | + "print(R1)\n", |
| 236 | + "print(R4)" |
| 237 | + ] |
64 | 238 | }, |
65 | 239 | { |
66 | 240 | "cell_type": "markdown", |
67 | 241 | "metadata": {}, |
68 | 242 | "source": [ |
69 | | - "### A note to delete later on\n", |
| 243 | + "So, that's how it works. Now scroll above a little and have a look at the cell titled \"Creating complicated sentences\". Do you notice something amiss? Now note that, the third argument in the 2nd line is `P & ~Q`. Now, how is that done? It's a statement, for sure, but it's not in the form of a string. As a matter of fact, `P` and `Q` are both `Expr`s themselves.\n", |
70 | 244 | "\n", |
71 | | - "1. Markdown is converted to HTML. It's closer to HTML than it is to Latex. Hence, to add special symbols, unicode characters etc., use HTML character reference rather than Latex symbols.\n", |
72 | | - "2. Propositional symbols in markdown\n", |
73 | | - " * ¬   `¬`\n", |
74 | | - " * ∧   `∧`\n", |
75 | | - " * ∨   `∨`\n", |
76 | | - " * →   `→`\n", |
77 | | - " * ↔   `↔`\n", |
78 | | - "3. And some others\n", |
79 | | - " * ⊨   `⊨`\n", |
80 | | - " * ≡   `≡`" |
| 245 | + "This is made possible because the `Expr` class overloads many operators. (It actually overloads mostly all the operators available in Python, but don't use them all; not, at least, for Propositional Logic.) Hence, you can do things like `P & ~Q` to *create `Expr`s by directly combining existing `Exprs`*. You might not immediately recognize the power and ease that this grants you, but I'll explain. Once, you have created some small, rudimentary expressions, you can use these overloaded operators to directly get your desired expressions; no need of using the `Expr` constructor each time. See how simple doing all that we did above becomes:" |
| 246 | + ] |
| 247 | + }, |
| 248 | + { |
| 249 | + "cell_type": "code", |
| 250 | + "execution_count": 11, |
| 251 | + "metadata": { |
| 252 | + "collapsed": false |
| 253 | + }, |
| 254 | + "outputs": [ |
| 255 | + { |
| 256 | + "name": "stdout", |
| 257 | + "output_type": "stream", |
| 258 | + "text": [ |
| 259 | + "P\n", |
| 260 | + "(A & B)\n", |
| 261 | + "(((C | D) >> E) >> (P & ~Q))\n" |
| 262 | + ] |
| 263 | + } |
| 264 | + ], |
| 265 | + "source": [ |
| 266 | + "# Some simple, rudimentary sentences\n", |
| 267 | + "P = Expr(\"P\")\n", |
| 268 | + "Q = Expr(\"Q\")\n", |
| 269 | + "A = Expr(\"A\")\n", |
| 270 | + "B = Expr(\"B\")\n", |
| 271 | + "C = Expr(\"C\")\n", |
| 272 | + "D = Expr(\"D\")\n", |
| 273 | + "E = Expr(\"E\")\n", |
| 274 | + "\n", |
| 275 | + "# Now for our complex expressions\n", |
| 276 | + "R1 = A & B\n", |
| 277 | + "R2 = (C | D) >> E\n", |
| 278 | + "\n", |
| 279 | + "# And the more complex expressions\n", |
| 280 | + "R3 = R1 % Q\n", |
| 281 | + "R4 = R2 >> (P & ~Q)\n", |
| 282 | + "\n", |
| 283 | + "# Let's print them and see if they are the same as before\n", |
| 284 | + "print(P)\n", |
| 285 | + "print(R1)\n", |
| 286 | + "print(R4)" |
81 | 287 | ] |
82 | 288 | }, |
83 | 289 | { |
84 | 290 | "cell_type": "markdown", |
85 | 291 | "metadata": {}, |
86 | 292 | "source": [ |
| 293 | + "Yes, yes they are. We cannot use `==>` and `<=>` when we use operator overloading, because those are not operators in Python. Instead, we have to use `>>` and `%` operators in their place. (Actually, `==>` and `<=>` are converted to `>>` and `%` internally.) Did you just cringe at using `%` for biconditionals? I am not too happy with that either. Ugly, I know, but for many reasons we *had to* implement it that way. But hey, it works like a charm.\n", |
| 294 | + "\n", |
| 295 | + "Before we move on, I would like to point out something that might cause you some confusion. The `==` and `!=` operators for `Expr`s. They do not logically evaluate two expressions and then check if they are equal. So don't do something like\n", |
| 296 | + "\n", |
87 | 297 | "```python\n", |
88 | | - "def my_function(string1, string2):\n", |
89 | | - " for in in range(42):\n", |
90 | | - " print string1 + string2\n", |
| 298 | + "A & (B | C) == (A & B) | (A & C)\n", |
91 | 299 | "```\n", |
92 | 300 | "\n", |
93 | | - "```python def __init__(self, sentence)```" |
| 301 | + "or even\n", |
| 302 | + "\n", |
| 303 | + "```python\n", |
| 304 | + "A & B == B & A\n", |
| 305 | + "```\n", |
| 306 | + "\n", |
| 307 | + "and expect it to return `True`. That's not how the `==` operator is intended to work. If you to know what it is supposed to do, have a look at the implementation of `__eq__`; that should tell you enough." |
| 308 | + ] |
| 309 | + }, |
| 310 | + { |
| 311 | + "cell_type": "markdown", |
| 312 | + "metadata": {}, |
| 313 | + "source": [ |
| 314 | + "### The `expr` function\n", |
| 315 | + "\n" |
94 | 316 | ] |
95 | 317 | }, |
96 | 318 | { |
|
100 | 322 | "collapsed": true |
101 | 323 | }, |
102 | 324 | "outputs": [], |
103 | | - "source": [ |
104 | | - "dcsdfdsf" |
105 | | - ] |
| 325 | + "source": [] |
106 | 326 | } |
107 | 327 | ], |
108 | 328 | "metadata": { |
109 | 329 | "kernelspec": { |
110 | | - "display_name": "Python 2", |
| 330 | + "display_name": "Python 3", |
111 | 331 | "language": "python", |
112 | | - "name": "python2" |
| 332 | + "name": "python3" |
113 | 333 | }, |
114 | 334 | "language_info": { |
115 | 335 | "codemirror_mode": { |
116 | 336 | "name": "ipython", |
117 | | - "version": 2 |
| 337 | + "version": 3 |
118 | 338 | }, |
119 | 339 | "file_extension": ".py", |
120 | 340 | "mimetype": "text/x-python", |
121 | 341 | "name": "python", |
122 | 342 | "nbconvert_exporter": "python", |
123 | | - "pygments_lexer": "ipython2", |
124 | | - "version": "2.7.11" |
| 343 | + "pygments_lexer": "ipython3", |
| 344 | + "version": "3.4.4" |
125 | 345 | } |
126 | 346 | }, |
127 | 347 | "nbformat": 4, |
|
0 commit comments