From 1215d9549e51c4d331745758f3278065246f1b29 Mon Sep 17 00:00:00 2001 From: ryuga4 Date: Tue, 14 May 2019 21:42:05 +0200 Subject: [PATCH] lepszy best first jeszcze --- Trunk/MonoGameView/Algorithms/BFS.cs | 7 +- .../Algorithms/BestFirstSearch.cs | 290 ++++++++++++++++++ Trunk/MonoGameView/Algorithms/DFS.cs | 7 +- .../MonoGameView/Algorithms/PriorityQueue.cs | 52 ++++ Trunk/MonoGameView/Game1.cs | 14 +- 5 files changed, 359 insertions(+), 11 deletions(-) create mode 100644 Trunk/MonoGameView/Algorithms/BestFirstSearch.cs create mode 100644 Trunk/MonoGameView/Algorithms/PriorityQueue.cs diff --git a/Trunk/MonoGameView/Algorithms/BFS.cs b/Trunk/MonoGameView/Algorithms/BFS.cs index aab1757..e8bbf8e 100644 --- a/Trunk/MonoGameView/Algorithms/BFS.cs +++ b/Trunk/MonoGameView/Algorithms/BFS.cs @@ -11,6 +11,7 @@ using System.Text; using System.Threading.Tasks; using Microsoft.Xna.Framework.Content; using System.Threading; +using CzokoŚmieciarka.MonoGameView.DataModels.GeneralModels.Models; namespace MonoGameView.Algorithms { @@ -93,7 +94,9 @@ namespace MonoGameView.Algorithms } } - if (!(itemdupa is House && collector.TrashContainers.All(i=>i.FillPercent==0))) + if (!(grid[collector.Coords.X, collector.Coords.Y] is Dump && collector.TrashContainers.Any(x => x.FillPercent > 0 && (grid[collector.Coords.X, collector.Coords.Y] as Dump).TypeOfGarbage.GarbageType == x.TypeOfGarbage.GarbageType)) + && !(grid[collector.Coords.X, collector.Coords.Y] is House + && (grid[collector.Coords.X, collector.Coords.Y] as House).TrashCans.Any(j => j.FillPercent > 0 && collector.TrashContainers.Any(i => i.FillPercent < 1 && i.Garbage.TypeOfGarbage.GarbageType == j.TypeOfGarbage.GarbageType)))) { var moveSteps = new List() { @@ -142,7 +145,7 @@ namespace MonoGameView.Algorithms while (true) { var item = nodes.Dequeue(); - //Thread.Sleep(10); + //Thread.Sleep(100); this.Collector.Coords = item.Item2.Coords; this.Collector.TrashContainers = item.Item2.TrashContainers; for (int x = 0; x < item.Item3.GetLength(0); x++) diff --git a/Trunk/MonoGameView/Algorithms/BestFirstSearch.cs b/Trunk/MonoGameView/Algorithms/BestFirstSearch.cs new file mode 100644 index 0000000..6037b73 --- /dev/null +++ b/Trunk/MonoGameView/Algorithms/BestFirstSearch.cs @@ -0,0 +1,290 @@ +using CzokoŚmieciarka.MonoGameView.DataModels.Enums; +using CzokoŚmieciarka.MonoGameView.DataModels.Interfaces; +using CzokoŚmieciarka.MonoGameView.DataModels.Interfaces.GarbageCollector; +using CzokoŚmieciarka.MonoGameView.DataModels.Interfaces.TrashCans; +using CzokoŚmieciarka.MonoGameView.DataModels.Models; +using CzokoŚmieciarka.MonoGameView.DataModels.Models.Steps; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Microsoft.Xna.Framework.Content; +using System.Threading; +using CzokoŚmieciarka.MonoGameView.DataModels.GeneralModels.Models; + +namespace MonoGameView.Algorithms +{ + public class BestFirstSearch + { + public GarbageCollector Collector { get; set; } + public ICloneable[,] Grid { get; set; } + public BestFirstSearch(GarbageCollector collector, ICloneable[,] grid) + { + this.Collector = collector; + this.Grid = grid; + } + int count = 0; + public List Houses { get; set; } + public List Dumps { get; set; } + public List BestPath(ContentManager content, GarbageCollector collector, ICloneable[,] grid) + { + Houses = new List(); + Dumps = new List(); + for (int x = 0; x < grid.GetLength(0); x++) + { + for (int y = 0; y < grid.GetLength(1); y++) + { + if (grid[x, y] is House) + { + Houses.Add(new Coords(x, y)); + + } else if (grid[x,y] is Dump) + { + Dumps.Add(new Coords(x, y)); + } + } + } + + + + var r = SearchBfs(content, collector, grid, 0).Key; + Console.WriteLine($"Counts : {count}"); + if (r == null) return new List(); + return r; + + } + + List PossibleSteps(AGarbageCollector collector, ICloneable[,] grid) + { + + + var result = new List(); + var itemdupa = grid[collector.Coords.X, collector.Coords.Y]; + + if (grid[collector.Coords.X, collector.Coords.Y] is House) + { + var collectSteps = new List() + { + new CollectStep(GarbageType.Glass), + new CollectStep(GarbageType.Organic), + new CollectStep(GarbageType.Paper), + new CollectStep(GarbageType.PlasticMetal) + }; + foreach (var item in collectSteps) + { + var copyCollector = (AGarbageCollector)collector.Clone(); + var copyGrid = CopyGrid(grid); + if (item.Invoke(copyCollector, copyGrid)) + result.Add(item); + } + } + if (grid[collector.Coords.X, collector.Coords.Y] is ADump) + { + var collectSteps = new List() + { + new SpillStep(GarbageType.Glass), + new SpillStep(GarbageType.Organic), + new SpillStep(GarbageType.Paper), + new SpillStep(GarbageType.PlasticMetal) + }; + foreach (var item in collectSteps) + { + var copyCollector = (AGarbageCollector)collector.Clone(); + var copyGrid = CopyGrid(grid); + if (item.Invoke(copyCollector, copyGrid)) + result.Add(item); + + + } + } + if (!(grid[collector.Coords.X, collector.Coords.Y] is Dump && collector.TrashContainers.Any(x => x.FillPercent > 0 && (grid[collector.Coords.X, collector.Coords.Y] as Dump).TypeOfGarbage.GarbageType == x.TypeOfGarbage.GarbageType)) + && !(grid[collector.Coords.X, collector.Coords.Y] is House + && (grid[collector.Coords.X, collector.Coords.Y] as House).TrashCans.Any(j => j.FillPercent > 0 && collector.TrashContainers.Any(i => i.FillPercent < 1 && i.Garbage.TypeOfGarbage.GarbageType == j.TypeOfGarbage.GarbageType)))) + { + var moveSteps = new List() + { + new MoveStep(Direction.Up), + new MoveStep(Direction.Down), + new MoveStep(Direction.Left), + new MoveStep(Direction.Right) + }; + var filteredMoveSteps = new List(); + foreach (var item in moveSteps) + { + var copyCollector = (AGarbageCollector)collector.Clone(); + if (item.Invoke(copyCollector, grid)) + { + var gcx = copyCollector.Coords.X; + var gcy = copyCollector.Coords.Y; + if (grid[gcx, gcy] is Road1 || grid[gcx, gcy] is House || (grid[gcx, gcy] is ADump && copyCollector.TrashContainers.Any(x => x.FillPercent > 0))) + { + result.Add(item); + } + } + + + } + + + } + return result; + } + + + + + int Priority (Tuple,GarbageCollector,ICloneable[,]> t) + { + var inHouses = Houses + .Aggregate(0.0, (a, b) => a + (t.Item3[b.X, b.Y] as IGarbageLocalization) + .TrashCans + .Aggregate(0.0, (i, j) => i + j.Garbage.Weight)); + var inDumps = Dumps + .Aggregate(0.0, (a, b) => a + (t.Item3[b.X, b.Y] as ATrashCan).Garbage.Weight); + var inCollector = t.Item2.TrashContainers.Aggregate(0.0, (a, b) => a + b.Garbage.Weight); + double p1 = inCollector + 2*inHouses - 3*inDumps; + + + var houses2 = Houses.Select(x => t.Item3[x.X, x.Y]).Where(x => x is House).Select(x => x as House).ToList(); + + var notFullCans = t.Item2.TrashContainers.Where(x => x.FillPercent != 1 + && houses2.Any(i=> i.TrashCans.Any(j => j.TypeOfGarbage.GarbageType == x.TypeOfGarbage.GarbageType + && j.FillPercent > 0)) ); + if (!notFullCans.Any()) + { + var fullCans = t.Item2.TrashContainers.Where(x => x.FillPercent > 0); + if (!fullCans.Any()) return 0; + //var fullCan=fullCans.First(); + var closestDump = Dumps + .Select(x => t.Item3[x.X, x.Y]) + .Select(i => i as Dump) + .Where(i => fullCans.Any(j=>i.TypeOfGarbage.GarbageType == j.TypeOfGarbage.GarbageType)) + .Min(b => Math.Pow(t.Item2.Coords.X - b.Coords.X, 2) + Math.Pow(t.Item2.Coords.Y - b.Coords.Y, 2)); + return (int) (p1 * 1000 + closestDump); + } + else + { + + + //var notFullCan = notFullCans.First(); + var closestHouses = Houses + .Select(x => t.Item3[x.X, x.Y]) + .Where(i => i is House) + .Select(i => i as House) + .Where(i => i.TrashCans.Any(x => notFullCans.Any(j=>x.TypeOfGarbage.GarbageType ==j.TypeOfGarbage.GarbageType && x.FillPercent > 0))); + var closestHouse = (closestHouses.Any()) ? closestHouses.Min(b => Math.Pow(t.Item2.Coords.X - b.Coords.X, 2) + Math.Pow(t.Item2.Coords.Y - b.Coords.Y, 2)): 0.0; + + var closestDumps = Dumps + .Select(x => t.Item3[x.X, x.Y]) + .Select(i => i as Dump) + .Where(i => notFullCans.Any(j=>i.TypeOfGarbage.GarbageType == j.TypeOfGarbage.GarbageType)); + var closestDump = (closestDumps.Any()) ? closestDumps.Min(b => Math.Pow(t.Item2.Coords.X - b.Coords.X, 2) + Math.Pow(t.Item2.Coords.Y - b.Coords.Y, 2)) : 0.0; + + + return (int) (p1 * 1000 + 10*closestHouse + closestDump); + } + } + + + + KeyValuePair, int> SearchBfs(ContentManager content, GarbageCollector collector, ICloneable[,] grid, int length) + { + + //Thread.Sleep(1); + int count = 0; + + var nodes = new PriorityQueue, GarbageCollector, ICloneable[,]>>(); + + var f = new Tuple, GarbageCollector, ICloneable[,]>(new List(), collector, grid); + + nodes.Enqueue(f,Priority(f)); + while (true) + { + var p = nodes.Dequeue(); + var item = p.Key; + var priority = p.Value; + + Thread.Sleep(100); + this.Collector.Coords = item.Item2.Coords; + this.Collector.TrashContainers = item.Item2.TrashContainers; + for (int x = 0; x < item.Item3.GetLength(0); x++) + { + for (int y = 0; y < item.Item3.GetLength(1); y++) + { + this.Grid[x, y] = item.Item3[x, y]; + } + } + + if (Houses.All(c => (item.Item3[c.X, c.Y] as IGarbageLocalization).TrashCans.All(j => j.FillPercent == 0.0)) + && + item.Item2.TrashContainers.All(i => i.FillPercent == 0.0) + ) + { + return new KeyValuePair, int>(item.Item1, length); + } + if (true)//item.Item2.Counter <= 12) + { + + + foreach (var step in PossibleSteps(item.Item2, item.Item3)) + { + if (step is SpillStep) + { + Console.WriteLine(); + } + var collectorClone = (GarbageCollector)item.Item2.Clone(); + var gridClone = CopyGrid(item.Item3); + step.Invoke(collectorClone, gridClone); + + + var steps = new List(); + steps.AddRange(item.Item1); + steps.Add(step); + var f2 = new Tuple, GarbageCollector, ICloneable[,]>(steps, collectorClone, gridClone); + var f2P = Priority(f2); + + nodes.Enqueue(f2,Priority(f2)); + } + } + + + } + } + + + + + + + + + + + + + + + + + + + + + + + private ICloneable[,] CopyGrid(ICloneable[,] grid) + { + ICloneable[,] result = new ICloneable[grid.GetLength(0), grid.GetLength(1)]; + for (int x = 0; x < grid.GetLength(0); x++) + { + for (int y = 0; y < grid.GetLength(1); y++) + { + result[x, y] = (ICloneable)grid[x, y].Clone(); + } + } + return result; + } + } +} + diff --git a/Trunk/MonoGameView/Algorithms/DFS.cs b/Trunk/MonoGameView/Algorithms/DFS.cs index 7b143e1..bf41d0d 100644 --- a/Trunk/MonoGameView/Algorithms/DFS.cs +++ b/Trunk/MonoGameView/Algorithms/DFS.cs @@ -12,6 +12,7 @@ using System.Threading.Tasks; using Microsoft.Xna.Framework.Content; using System.Threading; using MonoGameView.DataModels.Models; +using CzokoŚmieciarka.MonoGameView.DataModels.GeneralModels.Models; namespace CzokoŚmieciarka.MonoGameView.Algorithms { @@ -93,7 +94,9 @@ namespace CzokoŚmieciarka.MonoGameView.Algorithms } } - if (!(collector.TrashContainers.Any(x => x.FillPercent > 0) && grid[collector.Coords.X,collector.Coords.Y] is ADump)) + if (!(grid[collector.Coords.X,collector.Coords.Y] is Dump && collector.TrashContainers.Any(x => x.FillPercent > 0 && (grid[collector.Coords.X, collector.Coords.Y] as Dump).TypeOfGarbage.GarbageType == x.TypeOfGarbage.GarbageType )) + && !(grid[collector.Coords.X,collector.Coords.Y] is House + && (grid[collector.Coords.X, collector.Coords.Y] as House).TrashCans.Any(j => j.FillPercent > 0 && collector.TrashContainers.Any(i => i.FillPercent < 1 && i.Garbage.TypeOfGarbage.GarbageType == j.TypeOfGarbage.GarbageType)))) { var moveSteps = new List() { @@ -127,7 +130,7 @@ namespace CzokoŚmieciarka.MonoGameView.Algorithms KeyValuePair, int> Search(ContentManager content, GarbageCollector collector, ICloneable[,] grid, int length) { - //Thread.Sleep(10); + Thread.Sleep(100); this.Collector.Coords = collector.Coords; this.Collector.TrashContainers = collector.TrashContainers; diff --git a/Trunk/MonoGameView/Algorithms/PriorityQueue.cs b/Trunk/MonoGameView/Algorithms/PriorityQueue.cs new file mode 100644 index 0000000..1369087 --- /dev/null +++ b/Trunk/MonoGameView/Algorithms/PriorityQueue.cs @@ -0,0 +1,52 @@ +using System.Collections.Generic; + +public class PriorityQueue +{ + // The items and priorities. + List Values = new List(); + List Priorities = new List(); + + // Return the number of items in the queue. + public int NumItems + { + get + { + return Values.Count; + } + } + + // Add an item to the queue. + + public void AddAt(int index,T new_value, int new_priority) + { + Values.Insert(index, new_value); + Priorities.Insert(index, new_priority); + } + + public void Enqueue(T new_value, int new_priority) + { + var index = 0; + foreach (var item in Priorities) + { + if (item < new_priority) index++; + else break; + } + Values.Insert(index,new_value); + Priorities.Insert(index,new_priority); + } + + // Remove the item with the largest priority from the queue. + public KeyValuePair Dequeue() + { + // Find the hightest priority. + var best_index = 0; + + // Return the corresponding item. + var top_value = Values[best_index]; + var top_priotiy = Priorities[best_index]; + // Remove the item from the lists. + Values.RemoveAt(best_index); + Priorities.RemoveAt(best_index); + return new KeyValuePair(top_value,top_priotiy); + } +} \ No newline at end of file diff --git a/Trunk/MonoGameView/Game1.cs b/Trunk/MonoGameView/Game1.cs index 140ba0d..9daff1b 100644 --- a/Trunk/MonoGameView/Game1.cs +++ b/Trunk/MonoGameView/Game1.cs @@ -64,36 +64,36 @@ namespace CzokoŚmieciarka.MonoGameView // TODO: Add your initialization logic here timer = 0f; - mapLoader.Load(out size,out grid,"map12.xml"); + mapLoader.Load(out size,out grid,"mapa2.xml"); var containers = new List() { new GarbageCollectorContainer( new TypeOfGarbage(GarbageType.Glass,1), - 100000, + 10000, new BasicGarbage(new TypeOfGarbage(GarbageType.Glass,1),0) ), new GarbageCollectorContainer( new TypeOfGarbage(GarbageType.Paper,1), - 100000, + 10000, new BasicGarbage(new TypeOfGarbage(GarbageType.Paper,1),0) ), new GarbageCollectorContainer( new TypeOfGarbage(GarbageType.Organic,1), - 100000, + 10000, new BasicGarbage(new TypeOfGarbage(GarbageType.Organic,1),0) ), new GarbageCollectorContainer( new TypeOfGarbage(GarbageType.PlasticMetal,1), - 100000, + 10000, new BasicGarbage(new TypeOfGarbage(GarbageType.PlasticMetal,1),0) ), }; - collector = new GarbageCollector(new Coords(2,1), containers, size, size,0); + collector = new GarbageCollector(new Coords(1,1), containers, size, size,0); stepN = 0; - var dfs = new BestFirstSearch(collector,grid); + var dfs = new DFS(collector,grid); //steps = dfs.BestPath(Content, collector, grid); new Thread(delegate() { var x = dfs.BestPath(Content, collector, grid);