> For the complete documentation index, see [llms.txt](https://alham-rizvi.gitbook.io/alhamrizvi/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://alham-rizvi.gitbook.io/alhamrizvi/ai-college-notes/basics.md).

# Basics

## Chapter 1 - Full Basics (Read This Before Any Practical)

> This is the complete beginner's foundation for every practical we have done so far: BFS, DFS, A\*, the Table-Driven Vacuum Agent, Decision Trees, and SVM. If you are completely new to Python or AI, start here and read top to bottom. Every practical file assumes you already know everything in this chapter.

***

### 1.1 What language are we using, and how do I run it

We are using **Python 3** everywhere. It reads almost like English, and every AI/ML library (scikit-learn, TensorFlow, PyTorch) is built for it.

**How to run a Python file:**

1. Save your code in a file, for example `bfs.py`
2. Open a terminal in that folder
3. Run:

   ```bash
   python3 bfs.py
   ```

   On some Windows setups it may just be `python bfs.py`

**How to run in Google Colab** (used for the Decision Tree and SVM practicals): open colab.research.google.com, create a new notebook, type code into a cell, and press the Run/Play button on the left of that cell.

***

### 1.2 Python syntax crash course

#### Variables

No need to declare a type, just assign a value:

```python
start = 'Arad'      # a string (text)
count = 5           # an integer (whole number)
price = 4.5         # a float (decimal number)
```

#### Comments

```python
# Anything after a hash symbol is ignored by Python, used for notes to yourself
```

#### Indentation is not optional

Python uses **spaces/indentation** instead of curly braces `{ }` to define blocks of code, such as the inside of a function or a loop. This is the single biggest thing beginners get wrong.

```python
def greet():
    print("hello")   # this line belongs to greet() because it is indented
print("outside")     # this is NOT part of greet(), because it is not indented
```

#### Printing and f-strings

```python
name = "Ravi"
accuracy = 0.957
print("Hello", name)                  # Hello Ravi
print(f"Accuracy: {accuracy:.3f}")    # Accuracy: 0.957
```

An f-string, written as `f"..."`, lets you insert variables directly inside text using curly braces. The `:.3f` part means "show this number rounded to 3 decimal places," used heavily in the SVM practical's accuracy output.

#### Conditionals

```python
if action == "Stop":
    print("done")
elif action == "Suck":
    print("cleaning")
else:
    print("moving")
```

#### Loops

```python
for city in ['Arad', 'Sibiu', 'Bucharest']:
    print(city)

while not queue_is_empty:
    process_next_item()
```

***

### 1.3 Core data structures

#### (a) String

Text wrapped in quotes: `'Arad'`, `"Dirty"`.

#### (b) List

An ordered, changeable collection, written with square brackets:

```python
visited = []              # empty list
visited.append('Arad')    # add an item -> ['Arad']
'Arad' in visited          # check membership -> True
len(visited)                # how many items -> 1
```

Used for percept histories in the Vacuum Agent, and for feature rows (`X`) in the Decision Tree and SVM practicals.

#### (c) Tuple

Like a list, but **immutable** (cannot be changed after creation), written with round brackets:

```python
percept = ("A", "Dirty")
```

Tuples are used as dictionary keys throughout the Vacuum Agent practical, because Python dictionary keys must be immutable, and a list is not allowed to be a key, but a tuple is.

#### (d) Dictionary

Stores **key -> value** pairs. Think of it like a real dictionary, you look up a word (key) and get its meaning (value).

```python
person = {'name': 'Ravi', 'age': 20}
print(person['name'])   # Ravi
```

This is exactly how the road-map graphs in BFS, DFS, and A\* are stored:

```python
dict_gn = {
    'Arad': {'Zerind': 75, 'Sibiu': 140, 'Timisoara': 118}
}
```

This means Arad connects to Zerind (75 km), Sibiu (140 km), and Timisoara (118 km).

```python
dict_gn['Arad'].keys()   # gives all of Arad's neighbours: Zerind, Sibiu, Timisoara
```

And in the Vacuum Agent, a dictionary maps a whole percept history (tuple) to an action:

```python
lookup_table = {
    (("A", "Dirty"),): "Suck"
}
```

***

### 1.4 Queue, Stack, and Priority Queue (the 3 line-managers of search algorithms)

These three data structures decide the **order** in which a search algorithm explores things. Every search practical (BFS, DFS, A\*) is really the same basic idea, just with a different one of these three swapped in.

```mermaid
flowchart LR
    subgraph Queue - FIFO
    Q1[First in] --> Q2 --> Q3[First out]
    end
    subgraph Stack - LIFO
    S1[Last in] --> S3[First out]
    end
    subgraph Priority Queue
    P1[Lowest score] --> P2[Comes out first,\nregardless of order added]
    end
```

#### Queue (First In, First Out, used in BFS)

Works like a line at a ticket counter, whoever joins first, leaves first.

```python
import queue as Q
cityq = Q.Queue()
cityq.put('Arad')     # add to the back of the line
cityq.get()             # removes and returns the item at the FRONT
```

#### Stack (Last In, First Out, used in DFS)

Works like a stack of plates, whoever was placed last comes off first. DFS in our code uses a plain Python list this way, plus the recursive function call stack.

```python
stack = []
stack.append('Arad')   # push
stack.pop()             # pop, removes the LAST item added
```

#### Priority Queue (used in A\*)

Does not care about arrival order at all. It always serves whichever item currently has the **lowest priority number** first.

```python
import queue as q
cityq = q.PriorityQueue()
cityq.put((393, 'Arad,Sibiu', 'Sibiu'))   # (priority score, path, city)
cityq.get()   # always returns the item with the smallest first value
```

In A\*, that priority number is the f-score, `g(n) + h(n)`, so the path that currently looks most promising always comes out first, no matter when it was added.

***

### 1.5 Functions and recursion

A function is a reusable block of code:

```python
def add(a, b):
    return a + b

print(add(2, 3))   # 5
```

**Recursion** means a function calling itself, used heavily in both BFS and DFS.

```python
def countdown(n):
    if n == 0:               # base case: stops the recursion
        print("done")
        return
    print(n)
    countdown(n - 1)          # the function calls itself with a smaller problem
```

Every recursive function needs a **base case** (a stopping condition), or it will call itself forever and crash. In DFS, the base case is reaching the goal city. In BFS, the recursive call keeps pulling the next city off the queue until the goal is found.

#### The `global` keyword

```python
result = ''
def add_to_result(x):
    global result        # use the result defined OUTSIDE this function
    result = result + x  # instead of creating a new local variable
```

Used in both BFS and DFS to build up the final path string across many recursive calls.

***

### 1.6 Object-Oriented Programming basics (needed for the Vacuum Agent)

Practicals 1, 2, and 6 use plain functions. Practical 4 (the Vacuum Agent) introduces **classes**, a different style of organizing code, grouping related data and behaviour together into one object.

```mermaid
classDiagram
    class TableDrivenVacuumAgent {
        -percept_history : list
        -step : int
        -lookup_table : dict
        +perceive(location, status)
    }
```

```python
class TableDrivenVacuumAgent:
    def __init__(self):
        self.percept_history = []
        self.step = 0

    def perceive(self, location, status):
        ...
```

* `class TableDrivenVacuumAgent:` defines a **blueprint**. It does not do anything by itself, it just describes what any agent built from this blueprint will have and be able to do.
* `agent = TableDrivenVacuumAgent()` actually creates (this is called "instantiating") one real agent object from that blueprint.
* `__init__` is a special method that runs automatically, once, the moment an object is created. It is used to set up the object's starting data.
* `self` refers to "this particular object." Every method inside a class takes `self` as its first parameter, so it knows which object's data to work with. `self.percept_history` means "the percept\_history belonging to this specific agent."
* `self.percept_history = []` and `self.step = 0` are called **attributes**, pieces of data that belong to the object and stick around between method calls.
* `def perceive(self, location, status):` defines a **method**, a function that belongs to the class and can access/change the object's attributes using `self`.

**Why use a class here instead of plain variables and functions?** Because the agent needs to remember things (its percept history, its step count) across many separate calls to `perceive()`, one call per step. A class bundles that memory together with the logic that uses it, instead of having to pass a growing pile of variables around manually.

***

### 1.7 What is a Graph (the thing BFS, DFS, and A\* all search through)

A graph is a set of points, called **nodes**, connected by lines, called **edges**. In our practicals, nodes are cities and edges are roads with distances.

```mermaid
graph LR
    Arad --75--- Zerind
    Arad --140--- Sibiu
    Arad --118--- Timisoara
    Sibiu --99--- Fagaras
    Sibiu --80--- RimnicuVilcea
    Fagaras --211--- Bucharest
    RimnicuVilcea --97--- Pitesti
    Pitesti --101--- Bucharest
```

This is the famous **Romania map** problem, from the textbook *Artificial Intelligence: A Modern Approach* (Russell and Norvig), used everywhere to teach search algorithms.

* **Node / State**: a city, for example `'Arad'`
* **Start state**: where the search begins
* **Goal state**: where the search is trying to reach
* **Search**: the process of exploring nodes, one by one, following some strategy, until the goal is found

***

### 1.8 Search algorithm theory, all three types side by side

```mermaid
flowchart TD
    A[Search Algorithms] --> U[Uninformed / Blind Search]
    A --> I[Informed Search]
    U --> BFS[BFS: explores level by level, uses a Queue]
    U --> DFS[DFS: explores one path deeply first, uses a Stack]
    I --> ASTAR[A star: uses g plus h score, uses a Priority Queue]
```

|                                  | BFS                    | DFS                      | A\*                                                     |
| -------------------------------- | ---------------------- | ------------------------ | ------------------------------------------------------- |
| Category                         | Uninformed             | Uninformed               | Informed                                                |
| Data structure                   | Queue (FIFO)           | Stack / recursion (LIFO) | Priority Queue                                          |
| Knows extra info about the goal? | No                     | No                       | Yes, a heuristic estimate                               |
| Explores                         | Level by level         | Deep down one path first | Whichever path looks most promising overall             |
| Guarantees shortest path?        | Yes, in number of hops | No                       | Yes, in real cost, if the heuristic never overestimates |

**Uninformed search** (BFS, DFS) has no idea how far away the goal actually is, it just follows a fixed exploration order.

**Informed search** (A\*) uses a **heuristic**, `h(n)`, an estimate of the remaining distance from the current node to the goal, usually the straight line distance. It combines this with `g(n)`, the real cost travelled so far, into a total score:

```
f(n) = g(n) + h(n)
```

and always expands whichever path currently has the lowest `f(n)`.

```mermaid
flowchart LR
    G["g(n): real cost so far"] --> F["f(n) = g(n) + h(n)"]
    H["h(n): estimated cost remaining"] --> F
    F --> Decision[A* always expands the lowest f-score path next]
```

***

### 1.9 Machine Learning basics (needed for Decision Tree and SVM)

The last two practicals move from "search a map" to "learn from data," using the **scikit-learn** library. This is a different branch of AI called **Machine Learning**.

#### Supervised learning, in plain English

You give the computer a bunch of **examples** where you already know the correct answer, and it learns a general pattern it can then apply to brand new, unseen examples.

```mermaid
flowchart LR
    Data[Labeled training data:\nfeatures + correct answers] --> Train[Model learns a pattern]
    Train --> NewData[Brand new, unseen data]
    NewData --> Predict[Model predicts the answer]
```

#### Key vocabulary

| Term                                 | Meaning                                                                                                                 |
| ------------------------------------ | ----------------------------------------------------------------------------------------------------------------------- |
| **Feature(s), usually called X**     | The input measurements used to make a prediction, for example Age and Gender, or petal/sepal length and width           |
| **Label / Target, usually called y** | The correct answer for each example, for example Buy/Don't Buy, or which flower species                                 |
| **Training data**                    | Examples with known labels, used to teach the model                                                                     |
| **Test data**                        | Examples kept aside, never shown to the model during training, used afterward to check if it actually learned correctly |
| **Model**                            | The thing being trained, for example a Decision Tree or an SVM                                                          |
| **`.fit()`**                         | The scikit-learn method that actually performs the learning, using training data                                        |
| **`.predict()`**                     | The scikit-learn method that uses an already-trained model to guess labels for new data                                 |
| **Accuracy**                         | The fraction of test predictions that turned out to be correct                                                          |

#### Why split data into training and test sets

If you only ever check the model on data it already memorized during training, you cannot tell if it actually learned a real pattern, or simply memorized the answers. Testing on separate, unseen data is what proves real learning happened.

```python
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.25, random_state=42)
```

`random_state=42` fixes the randomness of the split, so the exact same split happens every time the code is run, this is why practical files can show one exact, reproducible output.

***

### 1.10 Decision Tree basics (entropy, in plain English)

A decision tree is a flowchart of yes/no questions ending in a decision, exactly like deciding "is it raining, then take an umbrella."

```mermaid
flowchart TD
    A[Root: Age <= 31.5?] -->|Yes| B[Don't Buy]
    A -->|No| C[Buy]
```

The computer decides which question to ask first using **entropy**, a measure of how "mixed up" a group of examples is.

* Entropy = 0 means the group is perfectly pure, every example has the same label.
* Entropy = 1 (for two classes) means a perfect 50/50 mix, maximum uncertainty.

The tree tries many possible questions and picks whichever one causes the **biggest drop in entropy**, called **Information Gain**, and that becomes the next split.

***

### 1.11 SVM basics (margin and kernel, in plain English)

Imagine red dots and blue dots scattered on paper. A Support Vector Machine finds the line (or curved boundary) that separates them with the **widest possible gap**, called the margin, between the boundary and the closest points of each colour.

```mermaid
flowchart LR
    A((Class A)) --- M[Widest possible gap]
    M --- B((Class B))
```

If the data cannot be separated cleanly by a straight line, SVM can use a **kernel**, a mathematical trick that reshapes the data into a higher dimension where a clean separating boundary becomes possible again. The RBF kernel, used in our SVM practical, is one of the most popular choices for this.

#### Why features are sometimes scaled first

`StandardScaler` rescales every feature to have a similar range, so that one feature (for example a column measured in the thousands) does not unfairly dominate another feature (measured in single digits) purely because of its scale, not because it is actually more important.

***

### 1.12 Quick map: which basics apply to which practical

| Practical        | Uses from this chapter                                                        |
| ---------------- | ----------------------------------------------------------------------------- |
| 1: BFS           | Dictionaries, Queue, recursion, global keyword, graphs                        |
| 2: DFS           | Dictionaries, lists as stacks, recursion, global keyword, graphs              |
| 4: Vacuum Agent  | Classes, `self`, `__init__`, tuples as dictionary keys, dictionaries          |
| 5: Decision Tree | Lists as feature rows, train\_test\_split, `.fit()`/`.predict()`, entropy     |
| 6: A\*           | Dictionaries, Priority Queue, recursion-free loop, heuristics, f = g + h      |
| SVM              | train\_test\_split, `.fit()`/`.predict()`, StandardScaler, margin/kernel idea |

***

### 1.13 You are now ready

You know:

* Python syntax, indentation, functions, recursion, and classes
* Lists, tuples, dictionaries, queues, stacks, and priority queues
* What a graph, node, state, and goal are
* The theory difference between uninformed search (BFS, DFS) and informed search (A\*)
* The basics of supervised machine learning, training/testing, entropy, and SVM margins

Move on to the individual practical files. Each one builds directly on the concepts explained here.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://alham-rizvi.gitbook.io/alhamrizvi/ai-college-notes/basics.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
