lepszy best first jeszcze

This commit is contained in:
ryuga4 2019-05-14 21:42:05 +02:00
parent 80902cc628
commit 1215d9549e
5 changed files with 359 additions and 11 deletions

View File

@ -11,6 +11,7 @@ using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.Xna.Framework.Content; using Microsoft.Xna.Framework.Content;
using System.Threading; using System.Threading;
using CzokoŚmieciarka.MonoGameView.DataModels.GeneralModels.Models;
namespace MonoGameView.Algorithms 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<IStep>() var moveSteps = new List<IStep>()
{ {
@ -142,7 +145,7 @@ namespace MonoGameView.Algorithms
while (true) while (true)
{ {
var item = nodes.Dequeue(); var item = nodes.Dequeue();
//Thread.Sleep(10); //Thread.Sleep(100);
this.Collector.Coords = item.Item2.Coords; this.Collector.Coords = item.Item2.Coords;
this.Collector.TrashContainers = item.Item2.TrashContainers; this.Collector.TrashContainers = item.Item2.TrashContainers;
for (int x = 0; x < item.Item3.GetLength(0); x++) for (int x = 0; x < item.Item3.GetLength(0); x++)

View File

@ -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<Coords> Houses { get; set; }
public List<Coords> Dumps { get; set; }
public List<IStep> BestPath(ContentManager content, GarbageCollector collector, ICloneable[,] grid)
{
Houses = new List<Coords>();
Dumps = new List<Coords>();
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<IStep>();
return r;
}
List<IStep> PossibleSteps(AGarbageCollector collector, ICloneable[,] grid)
{
var result = new List<IStep>();
var itemdupa = grid[collector.Coords.X, collector.Coords.Y];
if (grid[collector.Coords.X, collector.Coords.Y] is House)
{
var collectSteps = new List<IStep>()
{
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<IStep>()
{
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<IStep>()
{
new MoveStep(Direction.Up),
new MoveStep(Direction.Down),
new MoveStep(Direction.Left),
new MoveStep(Direction.Right)
};
var filteredMoveSteps = new List<IStep>();
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<List<IStep>,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<List<IStep>, int> SearchBfs(ContentManager content, GarbageCollector collector, ICloneable[,] grid, int length)
{
//Thread.Sleep(1);
int count = 0;
var nodes = new PriorityQueue<Tuple<List<IStep>, GarbageCollector, ICloneable[,]>>();
var f = new Tuple<List<IStep>, GarbageCollector, ICloneable[,]>(new List<IStep>(), 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<List<IStep>, 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<IStep>();
steps.AddRange(item.Item1);
steps.Add(step);
var f2 = new Tuple<List<IStep>, 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;
}
}
}

View File

@ -12,6 +12,7 @@ using System.Threading.Tasks;
using Microsoft.Xna.Framework.Content; using Microsoft.Xna.Framework.Content;
using System.Threading; using System.Threading;
using MonoGameView.DataModels.Models; using MonoGameView.DataModels.Models;
using CzokoŚmieciarka.MonoGameView.DataModels.GeneralModels.Models;
namespace CzokoŚmieciarka.MonoGameView.Algorithms 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<IStep>() var moveSteps = new List<IStep>()
{ {
@ -127,7 +130,7 @@ namespace CzokoŚmieciarka.MonoGameView.Algorithms
KeyValuePair<List<IStep>, int> Search(ContentManager content, GarbageCollector collector, ICloneable[,] grid, int length) KeyValuePair<List<IStep>, int> Search(ContentManager content, GarbageCollector collector, ICloneable[,] grid, int length)
{ {
//Thread.Sleep(10); Thread.Sleep(100);
this.Collector.Coords = collector.Coords; this.Collector.Coords = collector.Coords;
this.Collector.TrashContainers = collector.TrashContainers; this.Collector.TrashContainers = collector.TrashContainers;

View File

@ -0,0 +1,52 @@
using System.Collections.Generic;
public class PriorityQueue<T>
{
// The items and priorities.
List<T> Values = new List<T>();
List<int> Priorities = new List<int>();
// 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<T,int> 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<T,int>(top_value,top_priotiy);
}
}

View File

@ -64,36 +64,36 @@ namespace CzokoŚmieciarka.MonoGameView
// TODO: Add your initialization logic here // TODO: Add your initialization logic here
timer = 0f; timer = 0f;
mapLoader.Load(out size,out grid,"map12.xml"); mapLoader.Load(out size,out grid,"mapa2.xml");
var containers = new List<GarbageCollectorContainer>() var containers = new List<GarbageCollectorContainer>()
{ {
new GarbageCollectorContainer( new GarbageCollectorContainer(
new TypeOfGarbage(GarbageType.Glass,1), new TypeOfGarbage(GarbageType.Glass,1),
100000, 10000,
new BasicGarbage(new TypeOfGarbage(GarbageType.Glass,1),0) new BasicGarbage(new TypeOfGarbage(GarbageType.Glass,1),0)
), ),
new GarbageCollectorContainer( new GarbageCollectorContainer(
new TypeOfGarbage(GarbageType.Paper,1), new TypeOfGarbage(GarbageType.Paper,1),
100000, 10000,
new BasicGarbage(new TypeOfGarbage(GarbageType.Paper,1),0) new BasicGarbage(new TypeOfGarbage(GarbageType.Paper,1),0)
), ),
new GarbageCollectorContainer( new GarbageCollectorContainer(
new TypeOfGarbage(GarbageType.Organic,1), new TypeOfGarbage(GarbageType.Organic,1),
100000, 10000,
new BasicGarbage(new TypeOfGarbage(GarbageType.Organic,1),0) new BasicGarbage(new TypeOfGarbage(GarbageType.Organic,1),0)
), ),
new GarbageCollectorContainer( new GarbageCollectorContainer(
new TypeOfGarbage(GarbageType.PlasticMetal,1), new TypeOfGarbage(GarbageType.PlasticMetal,1),
100000, 10000,
new BasicGarbage(new TypeOfGarbage(GarbageType.PlasticMetal,1),0) 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; stepN = 0;
var dfs = new BestFirstSearch(collector,grid); var dfs = new DFS(collector,grid);
//steps = dfs.BestPath(Content, collector, grid); //steps = dfs.BestPath(Content, collector, grid);
new Thread(delegate() { new Thread(delegate() {
var x = dfs.BestPath(Content, collector, grid); var x = dfs.BestPath(Content, collector, grid);