---
# System prepended metadata

title: "\U0001F3AF A* (A-Star) Algorithm"
tags: [Autonomous-system]

---

# 🎯 A* (A-Star) Algorithm

`#pathfinding` `#graph-search` `#algorithms` `#heuristic-search` `#optimization`

<div style="background-color: #4A90E2; color: white; padding: 25px; border-radius: 10px; margin: 30px 0; font-size: 18px;">
<h1 style="color: white; font-size: 24px;">🎯 Quick Overview</h1>
A* is an informed search algorithm that combines Dijkstra's algorithm with heuristic estimation. It guarantees the shortest path while being more efficient than exhaustive searches by using heuristic functions to guide the search towards the goal.
</div>

## 📊 Visual Understanding of A*

### Basic A* Search Pattern
```mermaid
graph TD
    S((Start)) -->|f=0| A((A))
    S -->|f=2| B((B))
    A -->|f=3| C((C))
    B -->|f=4| D((D))
    C -->|f=5| G((Goal))
    D -->|f=6| G
    
    style S fill:#4CAF50
    style G fill:#FF5722
    style C fill:#2196F3
    style A fill:#2196F3
```
![image](https://hackmd.io/_uploads/HkxTCIPg1x.png)
![image](https://hackmd.io/_uploads/SJQeyDvlke.png)

## 📚 Introduction to A*

A* (pronounced "A-star") is one of the most popular and widely-used pathfinding algorithms, developed by Peter Hart, Nils Nilsson, and Bertram Raphael in 1968. It combines the benefits of both Dijkstra's algorithm and greedy best-first search.

### Core Principles
- **Best-First Search**: Always expands the most promising node
- **Heuristic Guidance**: Uses estimated cost to goal
- **Optimality**: Guarantees shortest path with admissible heuristics
- **Completeness**: Will always find a solution if one exists

<div style="background-color: #4A90E2; color: white; padding: 25px; border-radius: 10px; margin: 30px 0;">
<h2>🔑 Fundamental Components</h2>

1. **Cost Function f(n)**
   ```
   f(n) = g(n) + h(n)
   ```
   - g(n): Actual cost from start to node n
   - h(n): Estimated cost from n to goal
   - f(n): Total estimated path cost

2. **Data Structures**
   - Open List: Priority queue of nodes to explore
   - Closed List: Set of already explored nodes
   - Parent Map: Tracks optimal path

3. **Heuristic Function**
   - Manhattan Distance (Grid)
   - Euclidean Distance (Continuous)
   - Diagonal Distance (8-connected grid)
</div>

## 💻 Implementation

<div style="background-color: #040720; padding: 25px; border-radius: 10px; border-left: 5px solid #228be6;">

```python
class Node:
    def __init__(self, position, g=float('inf'), h=0):
        self.position = position
        self.g = g  # Cost from start to node
        self.h = h  # Estimated cost to goal
        self.f = g + h  # Total estimated cost
        self.parent = None

class AStar:
    def __init__(self, grid):
        self.grid = grid
        self.open_list = []
        self.closed_set = set()
        
    def manhattan_distance(self, p1, p2):
        return abs(p1[0] - p2[0]) + abs(p1[1] - p2[1])
    
    def get_neighbors(self, node):
        neighbors = []
        for dx, dy in [(0,1), (1,0), (0,-1), (-1,0)]:
            new_pos = (node.position[0] + dx, node.position[1] + dy)
            if self.is_valid(new_pos):
                neighbors.append(new_pos)
        return neighbors
    
    def find_path(self, start, goal):
        start_node = Node(start, g=0, h=self.manhattan_distance(start, goal))
        heapq.heappush(self.open_list, (start_node.f, start_node))
        
        while self.open_list:
            current_f, current_node = heapq.heappop(self.open_list)
            
            if current_node.position == goal:
                return self.reconstruct_path(current_node)
                
            self.closed_set.add(current_node.position)
            
            for neighbor_pos in self.get_neighbors(current_node):
                if neighbor_pos in self.closed_set:
                    continue
                    
                tentative_g = current_node.g + 1
                neighbor = Node(
                    neighbor_pos,
                    g=tentative_g,
                    h=self.manhattan_distance(neighbor_pos, goal)
                )
                
                if self.is_better_path(neighbor):
                    neighbor.parent = current_node
                    heapq.heappush(self.open_list, (neighbor.f, neighbor))
        
        return None
```
</div>

## 🔬 Advanced Features

### 1. Heuristic Functions
```python
def euclidean_distance(p1, p2):
    return ((p1[0] - p2[0])**2 + (p1[1] - p2[1])**2)**0.5

def diagonal_distance(p1, p2):
    dx = abs(p1[0] - p2[0])
    dy = abs(p1[1] - p2[1])
    return max(dx, dy) + (math.sqrt(2) - 1) * min(dx, dy)
```

### 2. Optimizations
- **Tie-Breaking**: Prefer paths towards goal
- **Binary Heap**: Efficient priority queue
- **Hash Table**: Fast node lookup

## ⚖️ Pros and Cons

<div style="background-color: #040720; padding: 25px; border-radius: 10px; margin: 20px 0;">
<h3>✅ Advantages</h3>

1. **Optimality**
   - Guaranteed shortest path
   - Optimal with admissible heuristics
   - Complete algorithm

2. **Efficiency**
   - More efficient than Dijkstra
   - Explores fewer nodes
   - Guided search direction

3. **Flexibility**
   - Works with any graph structure
   - Customizable heuristics
   - Handles different movement costs
</div>

<div style="background-color: #29465B; padding: 25px; border-radius: 10px; margin: 20px 0;">
<h3>❌ Disadvantages</h3>

1. **Memory Usage**
   - Stores all nodes in memory
   - Can be memory-intensive
   - Scales with search space

2. **Heuristic Dependency**
   - Performance relies on good heuristic
   - Poor heuristics reduce efficiency
   - Must be admissible for optimality

3. **Processing Overhead**
   - Priority queue operations
   - Path reconstruction cost
   - Heuristic calculations
</div>

[Would you like me to continue with the remaining sections (Applications, Comparison, etc.)?]