Commit 4856485e authored by Jakub Kaliszewski's avatar Jakub Kaliszewski

Poprawki Heurystyczne

Przesuwanka - całkowite przebudowanie.
parent 56ef46f5
......@@ -7,14 +7,14 @@ namespace MapaRumunii
{
private static void DisplaySolution(MapOfRomania problem, Node<City> result, Stopwatch stoper)
{
Console.Beep();
if (result == null)
{
Console.WriteLine("\nBrak rozwiązań!");
}
else
{
Console.WriteLine("Czas poszukiwania rozwiązania: " + stoper.Elapsed.Milliseconds / 1000.0 +
" s"); //zmienna z czasem);
Console.WriteLine("Czas poszukiwania rozwiązania: " + stoper.Elapsed);//zmienna z czasem
Console.WriteLine("Liczba kroków do znalezienia rozwiązania: " + TreeSearch<City>.CountOfSteps);
Console.WriteLine("Otrzymana Droga:");
result.ShowRoad(problem.ShowState);
......
......@@ -2,15 +2,6 @@
namespace MapaRumunii
{
internal enum Method
{
Stack,
Queue,
PriorityQueue,
AStar
}
internal static class TreeSearch<State>
{
public static int CountOfSteps { get; set; }
......@@ -61,16 +52,16 @@ namespace MapaRumunii
Func<Node<State>, State, double> calculatePriorityForAStar, Node<State> parent,
State newState)
{
switch (method)
switch (method.ToString())
{
case Method.PriorityQueue:
case ("PriorityQueue"):
{
return
calculatePriorityBestFirstSearch(
newState); //Priorytet względem odległości linii prostej do miasta docelowego
}
case Method.AStar:
case ("AStar"):
{
return parent.TotalRoad + calculatePriorityForAStar(parent, newState);
} // Priorytet względem Pokonanej już drogi + drogi od rodzica(do pokonania) + odległość "nowego Miasta" w linii prostej do celu
......
namespace Przesuwanka
using System;
namespace Przesuwanka
{
internal interface IFringe<Element>
{
bool IsEmpty { get; }
void Add(Element element);
Element Pop();
void SetCompareMethod(Func<Element, Element, bool> compareMethod);
}
}
\ No newline at end of file
......@@ -8,8 +8,8 @@ namespace Przesuwanka
bool IsGoal(State state);
bool Compare(State stateOfNode, State checkingState);
IList<State> Expand(State state);
IList<State> ExpandPriorityQueue(State state);
IList<State> ExpandAStar(State state);
void showState(State state);
int CountOfConflicts(State state);
int CountDistancesToGoal(State state);
double CountOfSteps { get; set; }
}
}
\ No newline at end of file
using System;
using System.Diagnostics;
namespace Przesuwanka
{
......@@ -7,32 +6,28 @@ namespace Przesuwanka
{
private readonly Node<State> parent;
public Node(State state, Node<State> parent, int count)
public Node(State state, Node<State> parent)
{
StateOfNode = state;
this.parent = parent;
this.CountOfSteps = count;
if (parent != null)
StepsForSolution = parent.StepsForSolution++;
else
StepsForSolution = 1;
}
public int CountOfSteps { get; set; }
public State StateOfNode { get; }
public State StateOfNode { get; }
public int StepsForSolution { get; set; }
public int Priority { get; set; }
public bool OnPathToRoot(State stateOfNode, State checkingState, Func<State, State, bool> Compare)
{
if (Compare(stateOfNode, checkingState)) //Stany są identyczne,
{
Debug.WriteLine("True");
return true;
}
if (parent == null) //Dalej juz nie moge, wiec nie wystapil
{
Debug.WriteLine("False");
return false;
}
Debug.WriteLine("Rekurencja");
return OnPathToRoot(parent, checkingState, Compare); //Dalej szukam stanu
}
......@@ -40,18 +35,10 @@ namespace Przesuwanka
private bool OnPathToRoot(Node<State> node, State checkingState, Func<State, State, bool> Compare)
{
if (Compare(node.StateOfNode, checkingState)) //Stany identyczne
{
Debug.WriteLine("True");
return true;
}
if (node.parent == null)
{
Debug.WriteLine("False");
return false;
}
if (node.parent == null) return false;
Debug.WriteLine("Rekurencja");
return OnPathToRoot(node.parent, checkingState, Compare); //Dalej szukam stanu
}
}
......
using System;
using System.Collections.Generic;
namespace nHetmans
{
//sortowanie przez scalanie time: O(nlogn), mem: O(n)
public class PriorityQueue<Element>
{
protected Func<Element, Element, bool> LessOrGreater;
private List<Element> ListOfNodes;
public PriorityQueue()
{
ListOfNodes = new List<Element>();
}
public virtual void SetCompareMethod(Func<Element, Element, bool> compareMethod)
{
LessOrGreater = compareMethod;
}
public void Add(Element element)
{
ListOfNodes.Add(element);
ListOfNodes = MergeSort(ListOfNodes);
}
public bool IsEmpty()
{
if (ListOfNodes.Count == 0) return true;
return false;
}
public Element Pop()
{
var result = ListOfNodes[0];
ListOfNodes.RemoveRange(0, 1);
return result;
}
private List<Element> MergeSort(List<Element> list)
{
if (list.Count <= 1)
return list;
var left = new List<Element>();
var right = new List<Element>();
for (var index = 0; index <= list.Count - 1; index++)
if (index < list.Count / 2)
left.Add(list[index]);
else
right.Add(list[index]);
left = MergeSort(left);
right = MergeSort(right);
return Merge(left, right);
}
private List<Element> Merge(List<Element> left, List<Element> right)
{
var result = new List<Element>();
while (left.Count != 0 && right.Count != 0)
if (LessOrGreater(left[0], right[0])) //left <= right then true; left => right then false
{
result.Add(left[0]);
left.RemoveRange(0, 1);
}
else
{
result.Add(right[0]);
right.RemoveRange(0, 1);
}
while (left.Count != 0)
{
result.Add(left[0]);
left.RemoveRange(0, 1);
}
while (right.Count != 0)
{
result.Add(right[0]);
right.RemoveRange(0, 1);
}
return result;
}
}
}
\ No newline at end of file
using System;
using Przesuwanka;
namespace nHetmans
{
public class PriorityQueueFringe<Element> : IFringe<Element>
{
private readonly PriorityQueue<Element> priorityQueue = new PriorityQueue<Element>();
public void Add(Element element)
{
priorityQueue.Add(element);
}
public bool IsEmpty => priorityQueue.IsEmpty();
public Element Pop()
{
return priorityQueue.Pop();
}
public virtual void SetCompareMethod(Func<Element, Element, bool> compareMethod)
{
priorityQueue.SetCompareMethod(compareMethod);
}
}
}
\ No newline at end of file
using System;
using System.Diagnostics;
using System.Threading;
using nHetmans;
namespace Przesuwanka
{
internal class Program
{
private static byte[,]
generateState(byte size) //Metoda na wygenerowanie tablicy wielowymiarowej, [0...size*size]
{
var tmpTable = new byte[size, size];
var posibleNumbers = new byte[size * size];
for (var i = 0; i < size * size; i++) posibleNumbers[i] = (byte) (i + 1);
posibleNumbers[size * size - 1] = 0;
var IndexnumberInPosibleNumbers = 0;
for (var i = 0; i < tmpTable.GetLength(0); i++)
for (var j = 0; j < tmpTable.GetLength(1); j++)
{
tmpTable[i, j] = posibleNumbers[IndexnumberInPosibleNumbers];
IndexnumberInPosibleNumbers++;
}
return tmpTable;
}
private static byte[,] mixGeneratedState(byte[,] table, byte numberOfMixes)
{
byte n1, m1, n2, m2, tmpValue;
var rnd = new Random();
for (byte i = 0; i < numberOfMixes; i++)
{
n1 = (byte) rnd.Next(0, table.GetLength(0));
m1 = (byte) rnd.Next(0, table.GetLength(0));
n2 = (byte) rnd.Next(0, table.GetLength(0));
m2 = (byte) rnd.Next(0, table.GetLength(0));
tmpValue = table[n1, m1];
table[n1, m1] = table[n2, m2];
table[n2, m2] = tmpValue;
}
return table;
}
public static void DisplaySolution(Przesuwanka przesuwanka, Node<byte[,]> result, Stopwatch stoper)
public static void DisplaySolution(Przesuwanka przesuwanka, Node<byte[,]> result, TimeSpan stoper)
{
Console.Beep();
Console.WriteLine();
showState(przesuwanka.InitialState);
if (result == null)
{
Console.WriteLine("\nNo solutions!");
Console.WriteLine("\nBrak rozwiązań!");
}
else
{
Console.WriteLine("\nGoal State: \n");
Console.WriteLine("Rozwiązanie:");
showState(result.StateOfNode);
Console.WriteLine("\nSteps: " + result.CountOfSteps);
Console.WriteLine("Time: " + stoper.Elapsed.Milliseconds / 1000.0 + " s"); //zmienna z czasem);
Console.WriteLine("Czas poszukiwania rozwiązania: " + stoper); //zmienna z czasem);
Console.WriteLine("Liczba kroków do znalezienia rozwiązania: " + przesuwanka.CountOfSteps);
Console.WriteLine("\nLiczba kroków rozwiązania: " + result.StepsForSolution);
Console.WriteLine("---------------------------------------------------------------------------");
przesuwanka.CountOfSteps = 0;
}
}
......@@ -75,60 +40,75 @@ namespace Przesuwanka
}
}
private static void Main(string[] args)
private enum Method
{
Console.WriteLine("Podaj wymiar przesuwanki: ");
var size = byte.Parse(Console.ReadLine());
Stack,
Queue,
PriorityQueue,
AStar
}
var initial = new byte[size, size];
byte numberOfMixes = 5; //Parametr ilosci przemieszan
var goal = new byte[size, size];
private static void Main()
{
Console.WriteLine("Podaj wymiar przesuwanki: ");
var size = byte.Parse(Console.ReadLine());
Console.WriteLine("Podaj wymiar ilość przelosowań: ");
var numberOfMixes = byte.Parse(Console.ReadLine());
/* byte[,] initial =
byte[,] initial =
{
{4, 1, 3},
{7, 2, 6},
{5, 8, 0},
};*/
initial = mixGeneratedState(generateState(size), numberOfMixes);
goal = generateState(size);
showState(initial);
{1, 8, 2},
{0, 4, 3},
{7, 6, 5},
};
//var problemPrzesuwanka = new Przesuwanka(size,initial);
var problemPrzesuwanka = new Przesuwanka(size, numberOfMixes);
problemPrzesuwanka.showState(problemPrzesuwanka.InitialState);
Node<byte[,]> result;
Stopwatch stoper = new Stopwatch();
TimeSpan elapsed = new TimeSpan();
var problemPrzesuwanka = new Przesuwanka(initial, goal);
Node<byte[,]> result;
Console.WriteLine("\nRozwiązywanie za pomocą BestFirstSearch (ilość płytek na złej pozycji)...");
var priorityQueueSolution = new PriorityQueueFringe<Node<byte[,]>>();
stoper.Start();
result = TreeSearch<byte[,]>.TreeSearchMethod(problemPrzesuwanka, priorityQueueSolution,
Method.PriorityQueue);
stoper.Stop();
elapsed = stoper.Elapsed;
DisplaySolution(problemPrzesuwanka, result, elapsed);
stoper.Reset();
/* Console.WriteLine("\nSolving with StackFringe...");
var stackSolution = new StackFringe<Node<byte[,]>>();
result = TreeSearch.TreeSearchMetod(problemPrzesuwanka, stackSolution);
DisplaySolution(problemPrzesuwanka, result);
TreeSearch.countOfSteps = 0;*/
Console.WriteLine("\nSolving with QueueFringe...");
var queueSolution = new QueueFringe<Node<byte[,]>>();
Stopwatch stoper = System.Diagnostics.Stopwatch.StartNew();
result = TreeSearch.TreeSearchMetod(problemPrzesuwanka, queueSolution);
Console.WriteLine(
"\nRozwiązywanie za pomocą A* (ilość płytek na złej pozycji + odległość Manhattan dla każdej płytki od pozycji, gdzie powinna się znajdować + ilość kroków, im ich mniej tym stan jest bardziej obiecujący)...");
var AStarSolution = new PriorityQueueFringe<Node<byte[,]>>();
stoper.Start();
result = TreeSearch<byte[,]>.TreeSearchMethod(problemPrzesuwanka, AStarSolution, Method.AStar);
stoper.Stop();
DisplaySolution(problemPrzesuwanka, result, stoper);
elapsed = stoper.Elapsed;
DisplaySolution(problemPrzesuwanka, result, elapsed);
stoper.Reset();
Console.WriteLine("\nSolving with PriorityQueueFringe...");
var priorityQueueSolution = new QueueFringe<Node<byte[,]>>();
Console.WriteLine("\nRozwiązywanie za pomocą Stosu...");
var stackSolution = new StackFringe<Node<byte[,]>>(); //DFS
stoper.Start();
result = TreeSearch.TreeSearchPriorityQueue(problemPrzesuwanka, priorityQueueSolution);
DisplaySolution(problemPrzesuwanka, result,stoper);
result = TreeSearch<byte[,]>.TreeSearchMethod(problemPrzesuwanka, stackSolution, Method.Stack);
stoper.Stop();
elapsed = stoper.Elapsed;
stoper.Reset();
DisplaySolution(problemPrzesuwanka, result, elapsed);
Console.WriteLine("\nSolving with AStarFringe...");
var AStarSolution = new QueueFringe<Node<byte[,]>>();
Console.WriteLine("\nRozwiązywanie za pomocą kolejki...");
var queueSolution = new QueueFringe<Node<byte[,]>>(); //BFS
stoper.Start();
result = TreeSearch.TreeSearchAStar(problemPrzesuwanka, AStarSolution);
DisplaySolution(problemPrzesuwanka, result,stoper);
result = TreeSearch<byte[,]>.TreeSearchMethod(problemPrzesuwanka, queueSolution, Method.Queue);
stoper.Stop();
elapsed = stoper.Elapsed;
DisplaySolution(problemPrzesuwanka, result, elapsed);
stoper.Reset();
}
}
}
\ No newline at end of file
This diff is collapsed.
......@@ -10,7 +10,7 @@
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>Przesuwanka</RootNamespace>
<AssemblyName>Przesuwanka</AssemblyName>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<TargetFrameworkVersion>v4.7</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
......@@ -24,7 +24,7 @@
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<PlatformTarget>x64</PlatformTarget>
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
......@@ -41,9 +41,11 @@
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="IFringe.cs" />
<Compile Include="IProblem.cs" />
<Compile Include="Interfaces\IFringe.cs"/>
<Compile Include="Interfaces\IProblem.cs"/>
<Compile Include="Node.cs" />
<Compile Include="PriorityQueue.cs"/>
<Compile Include="PriorityQueueFringe.cs"/>
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Przesuwanka.cs" />
......
using System.Collections.Generic;
using System;
using System.Collections.Generic;
namespace Przesuwanka
{
......@@ -17,5 +18,10 @@ namespace Przesuwanka
{
return queue.Dequeue();
}
public void SetCompareMethod(Func<Element, Element, bool> compareMethod)
{
return;
}
}
}
\ No newline at end of file
using System.Collections.Generic;
using System;
using System.Collections.Generic;
namespace Przesuwanka
{
......@@ -17,5 +18,10 @@ namespace Przesuwanka
{
return stack.Pop();
}
public void SetCompareMethod(Func<Element, Element, bool> compareMethod)
{
return;
}
}
}
\ No newline at end of file
......@@ -2,73 +2,77 @@
namespace Przesuwanka
{
internal static class TreeSearch
internal static class TreeSearch<State>
{
public static Node<State> TreeSearchMetod<State>(IProblem<State> problem, IFringe<Node<State>> fringe)
public static Node<State> TreeSearchMethod(IProblem<State> problem, IFringe<Node<State>> fringe, Enum method)
{
fringe.Add(new Node<State>(problem.InitialState, null, 1)); ///tworzy root na stosie
Func<Node<State>, int> calculatePriorityForBestFirstSearch = newState =>
problem.CountOfConflicts(newState.StateOfNode);
while (!fringe.IsEmpty)
{
Func<Node<State>, int> calculatePriorityForAStar = newstate =>
problem.CountDistancesToGoal(newstate.StateOfNode);
var node = fringe.Pop(); //zdjecie ze stosu
if (problem.IsGoal(node.StateOfNode)) //sprawdzenie zdjetego elementu ze stosu
return node;
foreach (var actualState in problem.Expand(node.StateOfNode)
) ///foreach-a z możliwymy stanami, to tam sprawdzam czy dany stan z IListy
/// już nie wystąpił, wywołując OnPathToRoot,
if (!node.OnPathToRoot(node.StateOfNode, actualState, problem.Compare)
) //Wykonuje sie gdy nie ma znalezionego identycznego stanu
fringe.Add(new Node<State>(actualState, node, node.CountOfSteps++));
}
fringe.SetCompareMethod(ComparePriority);
var initNode = new Node<State>(problem.InitialState, null);
initNode.Priority = CalculatePriorityMethod(method,
calculatePriorityForBestFirstSearch,
calculatePriorityForAStar, initNode);
return null;
}
public static Node<State> TreeSearchPriorityQueue<State>(IProblem<State> problem, IFringe<Node<State>> fringe)
{
fringe.Add(new Node<State>(problem.InitialState, null, 1)); ///tworzy root na stosie
fringe.Add(initNode); ///tworzy root na stosie
while (!fringe.IsEmpty)
{
var node = fringe.Pop(); //zdjecie ze stosu
if (problem.IsGoal(node.StateOfNode)) //sprawdzenie zdjetego elementu ze stosu
return node;
problem.CountOfSteps++;
foreach (var actualState in problem.ExpandPriorityQueue(node.StateOfNode))
///foreach-a z możliwymy stanami, to tam sprawdzam czy dany stan z IListy
/// już nie wystąpił, wywołując OnPathToRoot,
foreach (var actualState in problem.Expand(node.StateOfNode))
//foreach-a z możliwymy stanami, to tam sprawdzam czy dany stan z IListy
// już nie wystąpił, wywołując OnPathToRoot,
if (!node.OnPathToRoot(node.StateOfNode, actualState, problem.Compare))
//Wykonuje sie gdy nie ma znalezionego identycznego stanu
fringe.Add(new Node<State>(actualState, node, node.CountOfSteps++));
{
var nodeToAdd = new Node<State>(actualState, node);
nodeToAdd.Priority = CalculatePriorityMethod(method,
calculatePriorityForBestFirstSearch,
calculatePriorityForAStar, nodeToAdd);
fringe.Add(nodeToAdd);
}
}
return null;
}
public static Node<State> TreeSearchAStar<State>(IProblem<State> problem, IFringe<Node<State>> fringe)
private static int CalculatePriorityMethod(Enum method,
Func<Node<State>, int> calculatePriorityBestFirstSearch,
Func<Node<State>, int> calculatePriorityForAStar, Node<State> newState)
{
fringe.Add(new Node<State>(problem.InitialState, null, 1)); ///tworzy root na stosie
while (!fringe.IsEmpty)
switch (method.ToString())
{
var node = fringe.Pop(); //zdjecie ze stosu
if (problem.IsGoal(node.StateOfNode)) //sprawdzenie zdjetego elementu ze stosu
return node;
foreach (var actualState in problem.ExpandAStar(node.StateOfNode))
///foreach-a z możliwymy stanami, to tam sprawdzam czy dany stan z IListy
/// już nie wystąpił, wywołując OnPathToRoot,
if (!node.OnPathToRoot(node.StateOfNode, actualState, problem.Compare))
//Wykonuje sie gdy nie ma znalezionego identycznego stanu
fringe.Add(new Node<State>(actualState, node, node.CountOfSteps++));
case ("PriorityQueue"):
{
return calculatePriorityBestFirstSearch(newState); //Priorytet względem ilości płytek na złej pozycji
}
case ("AStar"):
{
return calculatePriorityForAStar(newState) + newState.StepsForSolution;
} //Priorytet względem ilości płytek na złej pozycji + odległość Manhattan dla każdej płytki od pozycji,
//gdzie powinna się znajdować + ilość kroków, im ich mniej tym stan jest bardziej obiecujący
default: return 0;
}
}
return null;
public static bool ComparePriority(Node<State> node1, Node<State> node2) //Metoda używana w sortowaniu
{
if (node1.Priority < node2.Priority) return true;
return false;
}
}
}
\ No newline at end of file
......@@ -5,19 +5,13 @@ namespace nHetmans
internal class Node<State>
{
private readonly Node<State> parent;
public Node(State state, Node<State> parent)
{
StateOfNode = state;
this.parent = parent;
StepsForSolution = 0;
}
public Node(State state, Node<State> parent, int stepsForSolution)
{
StateOfNode = state;
this.parent = parent;
StepsForSolution = stepsForSolution;
if(parent != null)
StepsForSolution = parent.StepsForSolution++;
}
public State StateOfNode { get; }
......
......@@ -8,6 +8,7 @@ namespace nHetmans
{
public static void DisplaySolution(Hetmans problemHetmans, Node<byte[]> result, Stopwatch stoper)
{
Console.Beep();
problemHetmans.ShowState(problemHetmans.InitialState);
if (result == null)
......@@ -18,8 +19,7 @@ namespace nHetmans
{
Console.WriteLine("Rozwiązanie:");
ShowState(result.StateOfNode);
Console.WriteLine("Czas poszukiwania rozwiązania: " + stoper.Elapsed.Milliseconds / 1000.0 +
" s"); //zmienna z czasem);
Console.WriteLine("Czas poszukiwania rozwiązania: " + stoper.Elapsed); //zmienna z czasem);
Console.WriteLine("Liczba kroków do znalezienia rozwiązania: " + TreeSearch<byte[]>.CountOfSteps);
Console.WriteLine("\nLiczba kroków rozwiązania: " + result.StepsForSolution);
Console.WriteLine("---------------------------------------------------------------------------");
......@@ -61,7 +61,6 @@ namespace nHetmans
Console.WriteLine("\nRozwiązywanie za pomocą Stosu...");
;
var stackSolution = new StackFringe<Node<byte[]>>();
var stoper = Stopwatch.StartNew();
result = TreeSearch<byte[]>.TreeSearchMethod(problemHetmans, stackSolution, Method.Stack);
......
......@@ -29,7 +29,7 @@ namespace nHetmans
if (!node.OnPathToRoot(node.StateOfNode, actualState, problem.Compare))
//Wykonuje sie gdy nie ma znalezionego identycznego stanu
{
var nodeToAdd = new Node<State>(actualState, node, node.StepsForSolution++);
var nodeToAdd = new Node<State>(actualState, node);
nodeToAdd.Priority = CalculatePriorityMethod(method, calculatePriorityForBestFirstSearch,
calculatePriorityForAStar, nodeToAdd);
......@@ -45,14 +45,14 @@ namespace nHetmans
Func<Node<State>, int> calculatePriorityBestFirstSearch,
Func<Node<State>, int> calculatePriorityForAStar, Node<State> newNode)
{
switch (method)
switch (method.ToString())
{