public MazeState Pop() { MazeState result = _states[0]; _states.RemoveAt(0); return(result); }
// remove and return first element from frontier - in addition // it is added to the searched list public MazeState PopFrontier() { MazeState result = Frontier.Pop(); Searched.Add(result); return(result); }
public MazeState Dequeue() { MazeState result = _states[_states.Count - 1]; _states.RemoveAt(_states.Count - 1); return(result); }
public MazeState(int[,] aState) { _state = aState; _parent = null; _children = null; Cost = 0; PathCost = 0; HeuristicCost = 0; TotalCost = Cost + HeuristicCost; }
//function used to generate goal state when no already identfied in constructor //static function public static int[,] GenerateGoalState(MazeState aStartState) { //get current position so it can be changed back to traversable path int[] curPos = aStartState.FindPosition(); int[,] result = MazeState.CloneState(aStartState.State); result[curPos[0], curPos[1]] = 1; //set curPos back to 1 (path) result[aStartState.State.GetLength(1) - 2, aStartState.State.GetLength(0) - 2] = 0; //set random position to goalstate return(result); }
public MazeState(int[,] aState, MazeState aParent, Direction aDFP, int aPathCost = 1) { _state = aState; _parent = aParent; _children = null; Cost = aParent.Cost + aPathCost; PathCost = aPathCost; HeuristicCost = 0; TotalCost = Cost + HeuristicCost; DirectionFromParent = aDFP; }
// returns the manhattan distance between two nodes public int GetManhattanDistance(MazeState aState, MazeState aDest) { //Find possition of two states int[] aCords = aState.FindPosition(); int[] bCords = aDest.FindPosition(); //calculate distance - returning absolute value //eg aCord : (4,4) bCord : (8, 8) //abs(4 - 8) + abs(4 - 8) = 8 return(Math.Abs(aCords[0] - bCords[0]) + Math.Abs(aCords[1] - bCords[1])); }
//check whether a maze state is in a container //implemented this since we can not simply write e.g Search.Contains(aState) since //it could not determine if they were equal. This is way we want a function to //compare the state of a maze only, rather than a whole MazeState Object. public static bool Contains(MazeState aState, List <MazeState> aContainer) { foreach (MazeState s in aContainer) { if (AreEqual(aState.State, s.State)) { return(true); } } return(false); }
//creates the child mazestates public List <MazeState> CreatePossibleMoves() { //get possble direction movements Direction[] possibleMovements = FindPossibleMovements(); Children = new List <MazeState>(); for (int i = 0; i < possibleMovements.Length; i++) { MazeState newState = Move(possibleMovements[i]); Children.Add(newState); } return(Children); }
//returns the closest goal state from the current state // - this funciton allows flexibility for the program to determine the // best goal to traverse to out of a collection public MazeState PickDesiredGoalState(MazeState aState, MazeState[] aGoalStates) { MazeState result = aGoalStates[0]; for (int i = 1; i < aGoalStates.Length; i++) { if (GetManhattanDistance(aState, result) > GetManhattanDistance(aState, aGoalStates[i])) { result = aGoalStates[i]; } } return(result); }
public Maze GetMaze(StreamReader rdr) { //Size of Maze string[] mazeSizeString = Between(rdr.ReadLine(), "[", "]").Split(','); int[] mazeSize = new int[2] { Convert.ToInt32(mazeSizeString[0]), Convert.ToInt32(mazeSizeString[1]) }; //Init state string[] initStateString = Between(rdr.ReadLine(), "(", ")").Split(','); int[] initState = new int[] { Convert.ToInt32(initStateString[0]), Convert.ToInt32(initStateString[1]) }; //Goal States string[] goalStatesString = rdr.ReadLine().Split('|'); goalStatesString = new string[] { Between(goalStatesString[0], "(", ")"), Between(goalStatesString[1], "(", ")") }; int[][] goalStates = new int[][] { new int[] { Convert.ToInt32(goalStatesString[0].Split(',')[0]), Convert.ToInt32(goalStatesString[0].Split(',')[1]) }, new int[] { Convert.ToInt32(goalStatesString[1].Split(',')[0]), Convert.ToInt32(goalStatesString[1].Split(',')[1]) } }; //Walls //Read out rest of mapconfig file List <int[]> wallsList = new List <int[]>(); while (!rdr.EndOfStream) { string[] wallsString = Between(rdr.ReadLine(), "(", ")").Split(','); wallsList.Add(new int[] { Convert.ToInt32(wallsString[0]), Convert.ToInt32(wallsString[1]), Convert.ToInt32(wallsString[2]), Convert.ToInt32(wallsString[3]) }); } int[][] walls = wallsList.ToArray(); //parse data to int[,] state int[,] startState = GenerateMazeState(mazeSize, initState, walls); int[,] goalStateA = GenerateMazeState(mazeSize, goalStates[0], walls); int[,] goalStateB = GenerateMazeState(mazeSize, goalStates[1], walls); //initialize MazeStates MazeState StartState = new MazeState(startState); MazeState[] GoalStates = new MazeState[goalStates.Length]; GoalStates[0] = new MazeState(goalStateA); GoalStates[1] = new MazeState(goalStateB); return(new Maze(StartState, GoalStates)); }
public override bool AddToFrontier(MazeState aState, Frontier aFrontier = null) { Frontier selectedFrontier = aFrontier == null ? Frontier : aFrontier; if (selectedFrontier.Contains(aState) || Maze.Contains(aState, Searched)) { return(false); } else { selectedFrontier.Enqueue(aState); } return(true); }
public void SortByCost() { for (int i = 0; i < _states.Count - 1; i++) { for (int j = 0; j < _states.Count - i - 1; j++) { if (_states[j].PathCost > _states[j + 1].PathCost) { MazeState temp = _states[j]; _states[j] = _states[j + 1]; _states[j + 1] = temp; } } } }
public void SortByEvaluationCost() { for (int i = 0; i < _states.Count - 1; i++) { for (int j = 0; j < _states.Count - i - 1; j++) { if (_states[j].GetTotalCost > _states[j + 1].GetTotalCost) { MazeState temp = _states[j]; _states[j] = _states[j + 1]; _states[j + 1] = temp; } } } }
//the variable cost bool is an option for different movement costs public MazeState Move(Direction aDirection) { //Get our current state position int[] position = FindPosition(); //create copy of this.State to be manipulated for new state MazeState result = new MazeState(CloneState(this.State), this, aDirection); switch (aDirection) { case Direction.Up: result.State[position[0], position[1] - 1] = 0; // set moved positioned to zero (new location1) if (SearchMethod.VariableCost) { result.Cost += 3; result.PathCost = 4; } break; case Direction.Left: result.State[position[0] - 1, position[1]] = 0; // set moved positioned to zero (new location1) if (SearchMethod.VariableCost) { result.Cost += 1; result.PathCost = 2; } break; case Direction.Down: result.State[position[0], position[1] + 1] = 0; // set moved positioned to zero (new location1) break; default: //right direction result.State[position[0] + 1, position[1]] = 0; // set moved positioned to zero (new location1) if (SearchMethod.VariableCost) { result.Cost += 1; result.PathCost = 2; } break; } //set previous position to traversable result.State[position[0], position[1]] = 1; return(result); }
public Maze(MazeState aStartState, MazeState[] aGoalStates) { //asign start and goal state(s) _startState = aStartState; _goalStates = aGoalStates; _iterations = new List <MazeState>(); _finalPathCost = 0; //initialize search alogorithms _bfs = new BreadthFirstSearch(); _dfs = new DepthFirstSearch(); _as = new AStarSearch(); _gbfs = new GreedyBestFirstSearch(); _ucs = new UniformCostSearch(); }
public override Direction[] Solve(Maze aMaze) { //push the StartState to the frontier AddToFrontier(aMaze.StartState); while (!Frontier.Empty()) { //Pop frontier state into curState MazeState curState = PopFrontier(); //check if curState is a goalState //using a loop for each of the varient goal states listed for (int i = 0; i < aMaze.GoalStates.Length; i++) { if (Maze.AreEqual(curState.State, aMaze.GoalStates[i].State)) { Maze.OutputState(curState.State); aMaze.FinalPathCost = curState.Cost; Console.WriteLine($"Path cost: {aMaze.FinalPathCost}"); iterationCount++; return(curState.GetPathFromParent()); } } //Find most desirable goal state - i.e. which is closes to the current state MazeState ClosestGoal = PickDesiredGoalState(curState, aMaze.GoalStates); //get all possible new states from curState List <MazeState> newStates = curState.CreatePossibleMoves(); //add all children frontier foreach (MazeState s in newStates) { //Need to implement a way to have a heuristic cost for each of the goal states s.HeuristicCost = GetManhattanDistance(s, ClosestGoal); AddToFrontier(s); } //Sort the frontier by f(n) = g(n) + h(n) Frontier.SortByEvaluationCost(); iterationCount++; } return(null); }
public override Direction[] Solve(Maze aMaze) { //ensure variable cost mode is on SearchMethod.VariableCost = true; AddToFrontier(aMaze.StartState); while (!Frontier.Empty()) { //Pop frontier state into curState MazeState curState = Frontier.Pop(); Searched.Add(curState); //check if curState is a goalState //using a loop for each of the varient goal states listed for (int i = 0; i < aMaze.GoalStates.Length; i++) { if (Maze.AreEqual(curState.State, aMaze.GoalStates[i].State)) { Maze.OutputState(curState.State); aMaze.FinalPathCost = curState.Cost; Console.WriteLine($"Path cost: {aMaze.FinalPathCost}"); iterationCount++; return(curState.GetPathFromParent()); } } //get all possible new states from curState List <MazeState> newStates = curState.CreatePossibleMoves(); foreach (MazeState s in newStates) { AddToFrontier(s); } iterationCount++; Frontier.SortByCost(); } return(null); }
public override Direction[] Solve(Maze aMaze) { //push the StartState to the frontier AddToFrontier(aMaze.StartState); while (!Frontier.Empty()) { //Pop frontier state into curState MazeState curState = Frontier.Dequeue(); Searched.Add(curState); //check if curState is a goalState //using a loop for each of the varient goal states listed for (int i = 0; i < aMaze.GoalStates.Length; i++) { if (Maze.AreEqual(curState.State, aMaze.GoalStates[i].State)) { Maze.OutputState(curState.State); aMaze.FinalPathCost = curState.Cost; Console.WriteLine($"Path cost: {aMaze.FinalPathCost}"); iterationCount++; return(curState.GetPathFromParent()); } } //get all possible new states from curState List <MazeState> newStates = curState.CreatePossibleMoves(); newStates.Reverse(); //Reverse elements to ensure priority is U > L > D > R foreach (MazeState s in newStates) { AddToFrontier(s); } iterationCount++; } return(null); }
//Returns a list of directions back from the starting node to the finishing node //ex. {Right, Right, Right, Down, Down, Down, Left....} public Direction[] GetPathFromParent() { Stack <Direction> result = new Stack <Direction>(); MazeState node = this; while (node != null) { //if our node is StartNode (cost 0) ignore and break loop if (node.Cost == 0) { break; } //push direction to result result.Push(node.DirectionFromParent); //set the parent variable to the parent of the last parent node = node.Parent; } //convert result Stack<Direction> into Array<Direction> return(result.ToArray()); }
public bool Contains(MazeState aState) { return(Maze.Contains(aState, _states)); }
//adds MazeState to end of linkedList public void Enqueue(MazeState aState) { _states.Add(aState); }
public abstract bool AddToFrontier(MazeState aState, Frontier aFrontier = null);
public void Push(MazeState aState) { _states.Insert(0, aState); }
static void Main(string[] args) { //Search Algorithm Information: https://www.geeksforgeeks.org/a-search-algorithm/ (Heuristic Calculations and more) //Check command-line args if (args.Length < 3) { Console.WriteLine("Required args: <mapconfig file> <search method> <variable move cost>"); Console.WriteLine("Map Config File: Enter filename with configuration OR enter 0 for random mazes"); Console.WriteLine("Search methods: DFS, BFS, AS, GBFS, CUS1"); Console.WriteLine("Variable move cost: 0 = false, 1 = true;"); System.Environment.Exit(0); } //assign args to variables string file = args[0]; string method = args[1]; SearchMethod.VariableCost = args[2] == "1" ? true : false; bool runtest = file == "0" ? true : false; //runtest if file == 0 //initalize Test Object MazeTest mazeTest = new MazeTest(400); //(50*50)/2 //create maze object Maze maze = new Maze(null, null); if (File.Exists(file)) { StreamReader rdr = new StreamReader(file); MazeGenerator mazeGenerator = new MazeGenerator(); maze = mazeGenerator.GetMaze(rdr); Output(maze, method); } else if (runtest) { int sizeIncrement = 20; for (int i = 0; i < 45; i++) { if (i > sizeIncrement) { sizeIncrement += 5; } Console.WriteLine($"Test iteration no: {i + 1}"); MazeState randomState = new MazeState(MazeGenerator.GenerateRandomMaze(sizeIncrement)); maze = new Maze(randomState); Output(maze, method); mazeTest.LogTest(maze.StartState.State.GetLength(0) * maze.StartState.State.GetLength(1), maze.FinalPathCost, maze.IterationCount); } mazeTest.OutputResults(); } else { Console.WriteLine($"The file: {file} was not found. Please try again!"); Environment.Exit(1); } }
public Maze(MazeState aStartState) : this(aStartState, null) { _goalStates = new MazeState[] { new MazeState(MazeGenerator.GenerateGoalState(aStartState)) }; }