Question
The project summary: The Sheep and Wolves problem is identical to the Guards & Prisoners problem from the lecture, except that it makes more semantic
The project summary: The Sheep and Wolves problem is identical to the Guards & Prisoners problem from the lecture, except that it makes more semantic sense why the wolves can be alone (they have no sheep to eat). Ignore for a moment the absurdity of wolves needing to outnumber sheep in order to overpower them. Maybe it's baby wolves vs. adult rams. As a reminder, the problem goes like this: you are a shepherd tasked with getting sheep and wolves across a river for some reason. If the wolves ever outnumber the sheep on either side of the river, the wolves will overpower and eat the sheep. You have a boat, which can only take one or two animals in it at a time, and must have at least one animal in it because you'll get lonely (and because the problem is trivial otherwise). How do you move all the animals from one side of the river to the other? In the original Sheep & Wolves (or Guards & Prisoners) problem, we specified there were 3 sheep and 3 wolves; here, though, your agent should be able to solve the problem for an arbitrary number of initial sheep and wolves. You may assume that the initial state of the problem will follow those rules (e.g. we won't give you more wolves than sheep to start). However, not every initial state will be solvable; there may be combinations of sheep and wolves that cannot be solved. You will return a list of moves that will solve the problem, or an empty list if the problem is unsolvable based on the initial set of Sheep and Wolves. You will also submit a brief report describing your approach. Using the python code below please elaborate on the questions: * How does your agent work? How does it generate new states, and how does it test them? * How well does your agent perform? Does it struggle on any particular cases? * How efficient is your agent? How does its performance change as the number of animals rises? * Does your agent do anything particularly clever to try to arrive at an answer more efficiently? * How does your agent compare to a human? Does your agent solve the problem the same way you would? import numpy as np from PIL import Image, ImageDraw, ImageFont import cv2 class State: def __init__(self, left_bank, right_bank, boat_position): self.left_bank = left_bank self.right_bank = right_bank self.boat_position = boat_position def is_valid(self): for bank in [self.left_bank, self.right_bank]: if bank[0] < bank[1] and bank[0] > 0: return False return True def is_goal(self, total_animals): return np.array_equal(self.right_bank, total_animals) def __eq__(self, other): return (np.array_equal(self.left_bank, other.left_bank) and np.array_equal(self.right_bank, other.right_bank) and self.boat_position == other.boat_position) def __hash__(self): return hash((tuple(self.left_bank), tuple(self.right_bank), self.boat_position)) class SemanticNetsAgent: def __init__(self): pass def solve(self, initial_sheep, initial_wolves): #If it is impossible to move the animals over according #to the rules of the problem, return an empty list of #moves. initial_state = State(np.array([initial_sheep, initial_wolves]), np.array([0, 0]), 'left') total_animals = np.array([initial_sheep, initial_wolves]) if not initial_state.is_valid(): return [] queue = [(initial_state, [])] visited = set() while queue: current_state, path = queue.pop(0) if current_state.is_goal(total_animals): return path if hash(current_state) in visited: continue visited.add(hash(current_state)) for move in generate_moves(current_state): new_state = apply_move(current_state, move) if new_state.is_valid(): new_path = path + [move] queue.append((new_state, new_path)) return [] # No solution found def generate_moves(state): moves = [] max_sheep = state.left_bank[0] if state.boat_position == 'left' else state.right_bank[0] max_wolves = state.left_bank[1] if state.boat_position == 'left' else state.right_bank[1] for s in range(min(2, max_sheep) + 1): for w in range(min(2 - s, max_wolves) + 1): if s + w > 0: moves.append((s, w)) return moves def apply_move(state, move): new_left = state.left_bank.copy() new_right = state.right_bank.copy() if state.boat_position == 'left': new_left -= move new_right += move new_boat_position = 'right' else: new_left += move new_right -= move new_boat_position = 'left' return State(new_left, new_right, new_boat_position) def create_state_image(state, total_animals, step, move=None): width, height = 800, 400 image = Image.new('RGB', (width, height), color='white') draw = ImageDraw.Draw(image) font = ImageFont.load_default() # Draw river draw.rectangle([width//3, 0, 2*width//3, height], fill='lightblue') # Draw banks draw.text((50, 10), f"Left Bank", font=font, fill='black') draw.text((width-150, 10), f"Right Bank", font=font, fill='black') # Draw animals sheep_emoji = "" wolf_emoji = "" for i in range(state.left_bank[0]): draw.text((50 + i*30, 50), sheep_emoji, font=font, fill='black') for i in range(state.left_bank[1]): draw.text((50 + i*30, 100), wolf_emoji, font=font, fill='black') for i in range(state.right_bank[0]): draw.text((width-150 + i*30, 50), sheep_emoji, font=font, fill='black') for i in range(state.right_bank[1]): draw.text((width-150 + i*30, 100), wolf_emoji, font=font, fill='black') # Draw boat boat_x = 250 if state.boat_position == 'left' else 550 draw.text((boat_x, height//2), "", font=font, fill='black') # Draw step and move information draw.text((10, height-30), f"Step: {step}", font=font, fill='black') if move: draw.text((10, height-60), f"Move: {move[0]} sheep, {move[1]} wolves", font=font, fill='black') return cv2.cvtColor(np.array(image), cv2.COLOR_RGB2BGR)
Step by Step Solution
There are 3 Steps involved in it
Step: 1
Get Instant Access to Expert-Tailored Solutions
See step-by-step solutions with expert insights and AI powered tools for academic success
Step: 2
Step: 3
Ace Your Homework with AI
Get the answers you need in no time with our AI-driven, step-by-step assistance
Get Started