Newer
Older
{
"cell_type": "markdown",
"metadata": {},
"source": [
"What is the funny `|'==>'|` syntax? The trick is that \"`|`\" is just the regular Python or-operator, and so is exactly equivalent to this: "
"outputs": [
{
"data": {
"text/plain": [
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"In other words, there are two applications of or-operators. Here's the first one:"
"outputs": [
{
"data": {
"text/plain": [
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"What is going on here is that the `__or__` method of `Expr` serves a dual purpose. If the right-hand-side is another `Expr` (or a number), then the result is an `Expr`, as in `(P | Q)`. But if the right-hand-side is a string, then the string is taken to be an operator, and we create a node in the abstract syntax tree corresponding to a partially-filled `Expr`, one where we know the left-hand-side is `P` and the operator is `==>`, but we don't yet know the right-hand-side.\n",
"The `PartialExpr` class has an `__or__` method that says to create an `Expr` node with the right-hand-side filled in. Here we can see the combination of the `PartialExpr` with `Q` to create a complete `Expr`:"
"outputs": [
{
"data": {
"text/plain": [
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"partial = PartialExpr('==>', P) \n",
"partial | ~Q"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"This [trick](http://code.activestate.com/recipes/384122-infix-operators/) is due to [Ferdinand Jamitzky](http://code.activestate.com/recipes/users/98863/), with a modification by [C. G. Vedant](https://github.com/Chipe1),\n",
"who suggested using a string inside the or-bars.\n",
"\n",
"## Appendix: The Implementation of `expr`\n",
"\n",
"How does `expr` parse a string into an `Expr`? It turns out there are two tricks (besides the Jamitzky/Vedant trick):\n",
"\n",
"1. We do a string substitution, replacing \"`==>`\" with \"`|'==>'|`\" (and likewise for other operators).\n",
"2. We `eval` the resulting string in an environment in which every identifier\n",
"is bound to a symbol with that identifier as the `op`.\n",
"\n",
"In other words,"
{
"cell_type": "code",
"outputs": [
{
"data": {
"text/plain": [
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"outputs": [
{
"data": {
"text/plain": [
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"P, Q = symbols('P, Q')\n",
"~(P & Q) |'==>'| (~P | ~Q)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"One thing to beware of: this puts `==>` at the same precedence level as `\"|\"`, which is not quite right. For example, we get this:"
]
},
{
"cell_type": "code",
"outputs": [
{
"data": {
"text/plain": [
"(((P & Q) ==> P) | Q)"
]
},
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"P & Q |'==>'| P | Q"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"which is probably not what we meant; when in doubt, put in extra parens:"
]
},
{
"cell_type": "code",
"outputs": [
{
"data": {
"text/plain": [
"((P & Q) ==> (P | Q))"
]
},
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"(P & Q) |'==>'| (P | Q)"
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Examples"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": true
},
"outputs": [],
"from notebook import Canvas_fol_bc_ask\n",
"canvas_bc_ask = Canvas_fol_bc_ask('canvas_bc_ask', crime_kb, expr('Criminal(x)'))"
]
},
"metadata": {
"collapsed": true
},
"This notebook by [Chirag Vartak](https://github.com/chiragvartak) and [Peter Norvig](https://github.com/norvig).\n",
}
],
"metadata": {
"kernelspec": {
"language": "python",
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
}
},
"nbformat": 4,