On this tutorial, we exhibit methods to mix the strengths of symbolic reasoning with neural studying to construct a robust hybrid agent. We concentrate on making a neuro-symbolic structure that makes use of classical planning for construction, guidelines, and goal-directed habits, whereas neural networks deal with notion and motion refinement. As we stroll via the code, we see how each layers work together in actual time, permitting us to navigate an surroundings, overcome uncertainty, and adapt intelligently. Finally, we perceive how neuro-symbolic techniques deliver interpretability, robustness, and adaptability collectively in a single agentic framework. Take a look at the FULL CODES here.
import numpy as np
import matplotlib.pyplot as plt
from dataclasses import dataclass, area
from typing import Record, Dict, Tuple, Set, Elective
from collections import deque
import warnings
warnings.filterwarnings('ignore')
@dataclass
class State:
robot_pos: Tuple[int, int]
holding: Elective[str] = None
visited: Set[Tuple[int, int]] = area(default_factory=set)
objects_collected: Set[str] = area(default_factory=set)
def __hash__(self):
return hash((self.robot_pos, self.holding))
class SymbolicPlanner:
def __init__(self, grid_size: int = 8):
self.grid_size = grid_size
self.actions = ['up', 'down', 'left', 'right', 'pickup', 'drop']
def get_successors(self, state: State, obstacles: Set[Tuple[int, int]], objects: Dict[str, Tuple[int, int]]) -> Record[Tuple[str, State]]:
successors = []
x, y = state.robot_pos
strikes = {'up': (x, y-1), 'down': (x, y+1), 'left': (x-1, y), 'proper': (x+1, y)}
for motion, new_pos in strikes.gadgets():
nx, ny = new_pos
if (0 <= nx < self.grid_size and 0 <= ny < self.grid_size and new_pos not in obstacles):
new_state = State(new_pos, state.holding, state.visited | {new_pos}, state.objects_collected.copy())
successors.append((motion, new_state))
if state.holding is None:
for obj_name, obj_pos in objects.gadgets():
if state.robot_pos == obj_pos and obj_name not in state.objects_collected:
new_state = State(state.robot_pos, obj_name, state.visited.copy(), state.objects_collected.copy())
successors.append(('pickup', new_state))
if state.holding shouldn't be None:
new_state = State(state.robot_pos, None, state.visited.copy(), state.objects_collected | {state.holding})
successors.append(('drop', new_state))
return successors
def heuristic(self, state: State, aim: Tuple[int, int]) -> float:
return abs(state.robot_pos[0] - aim[0]) + abs(state.robot_pos[1] - aim[1])
def a_star_plan(self, start_state: State, aim: Tuple[int, int], obstacles: Set[Tuple[int, int]], objects: Dict[str, Tuple[int, int]]) -> Record[str]:
counter = 0
frontier = [(self.heuristic(start_state, goal), counter, 0, start_state, [])]
visited = set()
whereas frontier:
frontier.type()
_, _, value, state, plan = frontier.pop(0)
counter += 1
if state.robot_pos == aim and len(state.objects_collected) >= len(objects):
return plan
state_key = (state.robot_pos, state.holding)
if state_key in visited:
proceed
visited.add(state_key)
for motion, next_state in self.get_successors(state, obstacles, objects):
new_cost = value + 1
new_plan = plan + [action]
precedence = new_cost + self.heuristic(next_state, aim)
frontier.append((precedence, counter, new_cost, next_state, new_plan))
counter += 1
return []
We lay the inspiration for our symbolic reasoning system and outline how states, actions, and transitions work. We implement classical planning logic utilizing A* search to generate goal-directed, interpretable motion sequences. As we construct this half, we set up the rule-based spine that guides the agent’s high-level choices. Take a look at the FULL CODES here.
class NeuralPerception:
def __init__(self, grid_size: int = 8):
self.grid_size = grid_size
self.W1 = np.random.randn(grid_size * grid_size, 64) * 0.1
self.b1 = np.zeros(64)
self.W2 = np.random.randn(64, 32) * 0.1
self.b2 = np.zeros(32)
self.W3 = np.random.randn(32, grid_size * grid_size) * 0.1
self.b3 = np.zeros(grid_size * grid_size)
def relu(self, x):
return np.most(0, x)
def sigmoid(self, x):
return 1 / (1 + np.exp(-np.clip(x, -500, 500)))
def understand(self, noisy_grid: np.ndarray) -> np.ndarray:
x = noisy_grid.flatten()
h1 = self.relu(x @ self.W1 + self.b1)
h2 = self.relu(h1 @ self.W2 + self.b2)
out = self.sigmoid(h2 @ self.W3 + self.b3)
return out.reshape(self.grid_size, self.grid_size)
class NeuralPolicy:
def __init__(self, state_dim: int = 4, action_dim: int = 4):
self.W = np.random.randn(state_dim, action_dim) * 0.1
self.b = np.zeros(action_dim)
self.action_map = ['up', 'down', 'left', 'right']
def softmax(self, x):
exp_x = np.exp(x - np.max(x))
return exp_x / exp_x.sum()
def get_action_probs(self, state_features: np.ndarray) -> np.ndarray:
logits = state_features @ self.W + self.b
return self.softmax(logits)
def select_action(self, state_features: np.ndarray, symbolic_action: str) -> str:
probs = self.get_action_probs(state_features)
if symbolic_action in self.action_map:
sym_idx = self.action_map.index(symbolic_action)
probs[sym_idx] += 0.7
probs = probs / probs.sum()
return np.random.alternative(self.action_map, p=probs)
We introduce the neural elements that enable our agent to sense and adapt. We design a light-weight neural community to denoise the surroundings and a easy coverage community to refine actions based mostly on options. As we combine these parts, we be certain that our agent can deal with uncertainty and regulate habits dynamically. Take a look at the FULL CODES here.
class NeuroSymbolicAgent:
def __init__(self, grid_size: int = 8):
self.grid_size = grid_size
self.planner = SymbolicPlanner(grid_size)
self.notion = NeuralPerception(grid_size)
self.coverage = NeuralPolicy()
self.obstacles = {(3, 3), (3, 4), (4, 3), (5, 5), (6, 2)}
self.objects = {'key': (2, 6), 'gem': (6, 6)}
self.aim = (7, 7)
def create_noisy_observation(self, true_grid: np.ndarray) -> np.ndarray:
noise = np.random.randn(*true_grid.form) * 0.2
return np.clip(true_grid + noise, 0, 1)
def extract_state_features(self, pos: Tuple[int, int], aim: Tuple[int, int]) -> np.ndarray:
return np.array([pos[0]/self.grid_size, pos[1]/self.grid_size, aim[0]/self.grid_size, aim[1]/self.grid_size])
def execute_mission(self, verbose: bool = True) -> Tuple[List, List]:
start_state = State(robot_pos=(0, 0), visited={(0, 0)})
symbolic_plan = self.planner.a_star_plan(start_state, self.aim, self.obstacles, self.objects)
if verbose:
print(f"🧠 Symbolic Plan Generated: {len(symbolic_plan)} steps")
print(f" Plan: {symbolic_plan[:10]}{'...' if len(symbolic_plan) > 10 else ''}n")
true_grid = np.zeros((self.grid_size, self.grid_size))
for obs in self.obstacles:
true_grid[obs[1], obs[0]] = 1.0
noisy_obs = self.create_noisy_observation(true_grid)
perceived_grid = self.notion.understand(noisy_obs)
if verbose:
print(f"👁️ Neural Notion: Denoised impediment map")
print(f" Notion accuracy: {np.imply((perceived_grid > 0.5) == true_grid):.2%}n")
trajectory = [(0, 0)]
current_pos = (0, 0)
actions_taken = []
for i, sym_action in enumerate(symbolic_plan[:30]):
options = self.extract_state_features(current_pos, self.aim)
refined_action = self.coverage.select_action(options, sym_action) if sym_action in ['up','down','left','right'] else sym_action
actions_taken.append(refined_action)
if refined_action == 'up': current_pos = (current_pos[0], max(0, current_pos[1]-1))
elif refined_action == 'down': current_pos = (current_pos[0], min(self.grid_size-1, current_pos[1]+1))
elif refined_action == 'left': current_pos = (max(0, current_pos[0]-1), current_pos[1])
elif refined_action == 'proper': current_pos = (min(self.grid_size-1, current_pos[0]+1), current_pos[1])
if current_pos not in self.obstacles:
trajectory.append(current_pos)
return trajectory, actions_taken
We deliver the symbolic and neural layers collectively right into a unified agent. We generate a symbolic plan, understand the surroundings via neural processing, and refine every deliberate motion utilizing the neural coverage. As we execute the mission loop, we observe how each techniques work together seamlessly to supply strong habits. Take a look at the FULL CODES here.
def visualize_execution(agent: NeuroSymbolicAgent, trajectory: Record, title: str = "Neuro-Symbolic Agent Execution"):
fig, axes = plt.subplots(1, 2, figsize=(14, 6))
ax = axes[0]
grid = np.zeros((agent.grid_size, agent.grid_size, 3))
for obs in agent.obstacles:
grid[obs[1], obs[0]] = [0.3, 0.3, 0.3]
for obj_pos in agent.objects.values():
grid[obj_pos[1], obj_pos[0]] = [1.0, 0.8, 0.0]
grid[agent.goal[1], agent.aim[0]] = [0.0, 1.0, 0.0]
for i, pos in enumerate(trajectory):
depth = 0.3 + 0.7 * (i / len(trajectory))
grid[pos[1], pos[0]] = [intensity, 0.0, 1.0]
if trajectory:
grid[trajectory[0][1], trajectory[0][0]] = [1.0, 0.0, 0.0]
ax.imshow(grid)
ax.set_title("Agent Trajectory in Atmosphere", fontsize=14, fontweight="daring")
ax.set_xlabel("X Place")
ax.set_ylabel("Y Place")
ax.grid(True, alpha=0.3)
ax = axes[1]
ax.axis('off')
ax.textual content(0.5, 0.95, "Neuro-Symbolic Structure", ha="heart", fontsize=16, fontweight="daring", rework=ax.transAxes)
layers = [("SYMBOLIC LAYER", 0.75, "Planning • State Logic • Rules"), ("↕ INTEGRATION", 0.60, "Feature Extraction • Action Blending"), ("NEURAL LAYER", 0.45, "Perception • Policy Learning"), ("↕ EXECUTION", 0.30, "Action Refinement • Feedback"), ("ENVIRONMENT", 0.15, "State Transitions • Observations")]
colours = ['#FF6B6B', '#4ECDC4', '#45B7D1', '#96CEB4', '#FFEAA7']
for i, (title, y, desc) in enumerate(layers):
ax.add_patch(plt.Rectangle((0.1, y-0.05), 0.8, 0.08, facecolor=colours[i], alpha=0.7, rework=ax.transAxes))
ax.textual content(0.5, y, f"{title}n{desc}", ha="heart", va="heart", fontsize=10, fontweight="daring", rework=ax.transAxes)
plt.tight_layout()
plt.savefig('neurosymbolic_agent.png', dpi=150, bbox_inches="tight")
plt.present()
print(f"n✅ Execution full! Trajectory size: {len(trajectory)} steps")
We visualize how the agent strikes via the surroundings and the way the structure is structured. We plot obstacles, objects, the aim, and the complete trajectory in order that we are able to clearly see the agent’s resolution course of. As we render the structure layers, we perceive how the hybrid design flows from planning to notion to motion. Take a look at the FULL CODES here.
if __name__ == "__main__":
print("=" * 70)
print("NEURO-SYMBOLIC HYBRID AGENT TUTORIAL")
print("Combining Classical AI Planning with Fashionable Neural Networks")
print("=" * 70)
print()
agent = NeuroSymbolicAgent(grid_size=8)
trajectory, actions = agent.execute_mission(verbose=True)
visualize_execution(agent, trajectory)
print("n" + "=" * 70)
print("KEY INSIGHTS:")
print("=" * 70)
print("✦ Symbolic Layer: Supplies interpretable, verifiable plans")
print("✦ Neural Layer: Handles noisy notion & adapts to uncertainty")
print("✦ Integration: Combines strengths of each paradigms")
print("✦ Advantages: Explainability + Flexibility + Robustness")
print("=" * 70)
We run the entire neuro-symbolic pipeline from planning to execution to visualization. We instantiate the agent, execute the mission, and show key insights to summarize the system’s habits. As we run this last block, we see the general hybrid structure in motion and recognize how every element contributes to the end result.
In conclusion, we observe how easily the symbolic and neural elements work collectively to supply a extra succesful and dependable agent. We recognize how the symbolic planner provides us clear, verifiable steps, whereas the neural layer provides adaptability and perceptual grounding that pure logic can’t provide. By this hybrid strategy, we are able to construct brokers that motive, understand, and act in methods which might be each clever and interpretable. We finish with a deeper understanding of how neuro-symbolic AI strikes us nearer to sensible, resilient agentic techniques.
Take a look at the FULL CODES here. Be happy to take a look at our GitHub Page for Tutorials, Codes and Notebooks. Additionally, be happy to comply with us on Twitter and don’t overlook to hitch our 100k+ ML SubReddit and Subscribe to our Newsletter. Wait! are you on telegram? now you can join us on telegram as well.
Asif Razzaq is the CEO of Marktechpost Media Inc.. As a visionary entrepreneur and engineer, Asif is dedicated to harnessing the potential of Synthetic Intelligence for social good. His most up-to-date endeavor is the launch of an Synthetic Intelligence Media Platform, Marktechpost, which stands out for its in-depth protection of machine studying and deep studying information that’s each technically sound and simply comprehensible by a large viewers. The platform boasts of over 2 million month-to-month views, illustrating its reputation amongst audiences.
