Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Notebook: Logical Agents - 3e #453

Merged
merged 3 commits into from
Mar 12, 2019
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
277 changes: 277 additions & 0 deletions notebooks/LogicalAgents.ipynb
Original file line number Diff line number Diff line change
@@ -0,0 +1,277 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Logical Agents"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"%classpath add jar ../out/artifacts/aima_core_jar/aima-core.jar"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
" This notebook serves as a supporting material for the chapter **Logical Agents**. The notebooks illustrate the use of the code repository and demonstrate how the code can be extended to solve various related problems. We begin with overall agent design, introduce a simple new environment, the wumpus world, and illustrate the operation of knowledge-based agent. Then we have a look at the gernal principles of **logic** and the specifics of **propositional logic** and with well-developed inference technologies. At last, we combine the concept of knowledge-based agents with technology of propositional logic to build some simple agents for the wumpus world."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Knowledge-Based Agents"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The central component of a knowledge-based agent is its **knowledge base**, or **KB**. A knowledge base is a set of **sentences**. (Here “sentence” is used as a technical term. It is related but not identical to the sentences of English and other natural languages.) Each sentence is expressed in a language called a **knowledge representation language** and represents some assertion about the world. Sometimes we dignify a sentence with the name **axiom**, when the\n",
"sentence is taken as given without being derived from other sentences.\n",
"\n",
"There must be a way to add new sentences to the knowledge base and a way to query what is known. The standard names for these operations are TELL and ASK, respectively.Both operations may involve **inference**—that is, deriving new sentences from old. Inference must obey the requirement that when one ASKs a question of the knowledge base, the answer should follow from what has been told (or TELLed) to the knowledge base previously."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The pseudocode below shows the outline of a knowledge-based agent program. Like all other agents, it takes a percept as input and returns an action. The agent maintaining knowlege base, KB, which may initially contain some **background knowledge*"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [
{
"data": {
"text/markdown": [
"### AIMA3e\n",
"__function__ KB-AGENT(_percept_) __returns__ an _action_ \n",
" __persistent__: _KB_, a knowledge base \n",
"      _t_, a counter, initially 0, indicating time \n",
"\n",
" TELL(_KB_, MAKE\\-PERCEPT\\-SENTENCE(_percept_, _t_)) \n",
" _action_ ← ASK(_KB_, MAKE\\-ACTION\\-QUERY(_t_)) \n",
" TELL(_KB_, MAKE\\-ACTION\\-SENTENCE(_action_, _t_)) \n",
" _t_ ← _t_ + 1 \n",
" __return__ _action_ \n",
"\n",
"---\n",
"__Figure__ ?? A generic knowledge\\-based agent. Given a percept, the agent adds the percept to its knowledge base, asks the knowledge base for the best action, and tells the knowledge base that it has in fact taken that action."
],
"text/plain": [
"<IPython.core.display.Markdown object>"
]
},
"execution_count": 2,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"from notebookUtils import *\n",
"pseudocode('KB-Agent')"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The implementation of the above pseudocode can be viewed [here](https://github.com/aimacode/aima-java/blob/AIMA3e/aima-core/src/main/java/aima/core/logic/propositional/agent/KBAgent.java). This agent is implemented as an abstract agent which can be extended to construct other agents."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Propositional Logic"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"We now present a simple but powerful logic called **propositional logic**. We cover the syntax of propositional logic and its semantics—the way in which the truth of sentences is determined. Then we look at **entailment**—the relation between a sentence and another sentence that follows from it—and see how this leads to a simple algorithm for logical inference. Everything takes place, of course, in the wumpus world."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### 1. Syntax"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The syntax of propositional logic defines the allowable sentences. The atomic sentences consist of a single **proposition symbol**. Each such symbol stands for a proposition that can be true or false. We use symbols that start with an uppercase letter and may contain other letters or subscripts.The names are arbitrary but are often chosen to have some mnemonic value—we use W<sub>1, 3</sub> to stand for the proposition that the wumpus is in [1,3]. (Remember that symbols such as W<sub>1,3</sub> are *atomic*, i.e., W, 1,and 3 are not meaningful parts of the symbol.) There are two proposition symbols with fixed\n",
"meanings: *True* is the always-true proposition and *False* is the always-false proposition."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Complex sentences** are constructed from simpler sentences, using parentheses and logical connectives. There are five connectives in common use:\n",
"\n",
"\n",
"* ¬ (not). A sentence such as ¬W<sub>1,3</sub> is called the **negation** of W<sub>1,3</sub>. A literal is either an atomic sentence (a **positive literal**) or a negated atomic sentence (a **negative literal**).\n",
"\n",
"* ∧ (and). A sentence whose main connective is ∧, such as W<sub>1, 3</sub> ∧ P<sub>3, 1</sub>, is called a **conjunction**; its parts are the **conjuncts**.\n",
"\n",
"* ∨ (or). A sentence using ∨, such as (W<sub>1, 3</sub> ∧ P<sub>3, 1</sub>)∨W<sub>2, 2</sub>, is a **disjunction** of the **disjuncts**\n",
"(W<sub>1, 3</sub> ∧ P<sub>3, 1</sub>) and W<sub>2, 2</sub>.\n",
"\n",
"* ⇒ (implies). A sentence such as (W<sub>1, 3</sub> ∧ P<sub>3, 1</sub>) ⇒ ¬W<sub>2, 2</sub> is called an **implication** (or conditional). Its **premise** or **antecedent** is (W<sub>1, 3</sub> ∧ P<sub>3, 1</sub>), and its **conclusion** or **consequent** is ¬W<sub>2, 2</sub>. Implications are also known as **rules** or **if–then** statements. The implication symbol is sometimes written in other books as ⊃ or →.\n",
"\n",
"* ⇔ (if and only if). The sentence W<sub>1, 3</sub> ⇔ ¬W<sub>2, 2</sub> is a biconditional. Some other books write this as ≡."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The implementation of forming **Complex Sentences** is [here](https://github.com/aimacode/aima-java/blob/AIMA3e/aima-core/src/main/java/aima/core/logic/propositional/parsing/ast/ComplexSentence.java). The Complex sentence is implemented using [Sentence](https://github.com/aimacode/aima-java/blob/AIMA3e/aima-core/src/main/java/aima/core/logic/propositional/parsing/ast/Sentence.java) and requires [Connective](https://github.com/aimacode/aima-java/blob/AIMA3e/aima-core/src/main/java/aima/core/logic/propositional/parsing/ast/Connective.java) to form it properly."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### 2. Semantics"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The semantics defines the rules for determining the truth of a sentence with respect to a particular model. In propositional logic, a model simply fixes the **truth value**—*true* or *false*—for every proposition symbol"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The semantics for propositional logic must specify how to compute the truth value of any sentence, given a model. This is done recursively. All sentences are constructed from [AtomicSentence](https://github.com/aimacode/aima-java/blob/AIMA3e/aima-core/src/main/java/aima/core/logic/propositional/parsing/ast/AtomicSentence.java) and the five connectives; therefore, we need to specify how to compute the truth of atomic sentences and how to compute the truth of sentences formed with each of the five connectives. Atomic sentences are easy:\n",
"* *True* is true in every model and *False* is false in every model.\n",
"* The truth value of every other proposition symbol must be specified directly in the model."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"For complex sentences, we have five rules, which hold for any subsentences *P* and *Q* in any model *m* (here “iff” means “if and only if”):\n",
"* ¬*P* is true iff *P* is false in *m*.\n",
"* *P* ∧ *Q* is true iff both *P* and *Q* are true in *m*.\n",
"* *P* ∨ *Q* is true iff either *P* or *Q* is true in *m*.\n",
"* *P* ⇒ *Q* is true unless *P* is true and *Q* is false in *m*.\n",
"* *P* ⇔ *Q* is true iff *P* and *Q* are both true or both false in *m*."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Truth Table Entailment"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"*Truth-Table Entails* performs a recursive enumeration of a finite space of assignments to symbols. The algorithm is **sound** because it implements directly the definition of entailment, and complete because it works for any KB\n",
"and α and always terminates—there are only finitely many models to examine.\n",
"\n",
"Of course, “finitely many” is not always the same as “few.” If *KB* and *α* contain *n* symbols in all, then there are *2<sup>n<sup>* models. Thus, the time complexity of the algorithm is *O(2n)*. (The space complexity is only *O(n)* because the enumeration is depth-first.) Unfortunately, propositional entailment is co-NP-complete (i.e., probably no easier than NP-complete), so *every known inference algorithm for propositional logic has a worst-case\n",
"complexity that is exponential in the size of the input.*"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [
{
"data": {
"text/markdown": [
"### AIMA3e\r\n",
"__function__ TT-ENTAILS?(_KB_, _&alpha;_) __returns__ _true_ or _false_ \r\n",
"&emsp;__inputs__: _KB_, the knowledge base, a sentence in propositional logic \r\n",
"&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;_&alpha;_, the query, a sentence in propositional logic \r\n",
"\r\n",
"&emsp;_symbols_ &larr; a list of the propositional symbols in _KB_ and _&alpha;_ \r\n",
"&emsp;__return__ TT-CHECK-ALL(_KB_, _&alpha;_, _symbols_, { }) \r\n",
"\r\n",
"---\r\n",
"__function__ TT-CHECK-ALL(_KB_, _&alpha;_, _symbols_, _model_) __returns__ _true_ or _false_ \r\n",
"&emsp;__if__ EMPTY?(_symbols_) __then__ \r\n",
"&emsp;&emsp;&emsp;__if__ PL-TRUE?(_KB_, _model_) __then return__ PL-TRUE?(_&alpha;_, _model_) \r\n",
"&emsp;&emsp;&emsp;__else return__ _true_&emsp;_//_&emsp;_when KB is false, always return true_ \r\n",
"&emsp;__else do__ \r\n",
"&emsp;&emsp;&emsp;_P_ &larr; FIRST(_symbols_) \r\n",
"&emsp;&emsp;&emsp;_rest_ &larr; REST(_symbols_) \r\n",
"&emsp;&emsp;&emsp;__return__(TT-CHECK-ALL(_KB_, _&alpha;_, _rest_, _model_ &cup; { _P_ = _true_ }) \r\n",
"&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;__and__ \r\n",
"&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;TT-CHECK-ALL(_KB_, _&alpha;_, _rest_, _model_ &cup; { _P_ = _false_ })) \r\n",
" \r\n",
"\r\n",
"---\r\n",
"__Figure__ ?? A truth-table enumeration algorithm for deciding propositional entailment. (TT stands for truth table.) PL-TRUE? returns _true_ if a sentence holds within a model. The variable _model_ represents a partial model \\- an assignment to some of the symbols. The keyword \"__and__\" is used here as a logical operation on its two arguments, returning _true_ or _false_."
],
"text/plain": [
"<IPython.core.display.Markdown object>"
]
},
"execution_count": 1,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"from notebookUtils import *\n",
"pseudocode('TT-Entails')"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "Java",
"language": "java",
"name": "java"
},
"toc": {
"base_numbering": 1,
"nav_menu": {},
"number_sections": false,
"sideBar": false,
"skip_h1_title": false,
"title_cell": "Table of Contents",
"title_sidebar": "Contents",
"toc_cell": false,
"toc_position": {},
"toc_section_display": false,
"toc_window_display": false
}
},
"nbformat": 4,
"nbformat_minor": 2
}