317 lines
10 KiB
C#
317 lines
10 KiB
C#
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;
|
|
using MonoGameView.DataModels.Models;
|
|
|
|
namespace MonoGameView.Algorithms
|
|
{
|
|
public class Vowpal
|
|
{
|
|
public GarbageCollector Collector { get; set; }
|
|
public ICloneable[,] Grid { get; set; }
|
|
public Vowpal(GarbageCollector collector, ICloneable[,] grid)
|
|
{
|
|
this.Collector = collector;
|
|
this.Grid = grid;
|
|
}
|
|
int count = 0;
|
|
public List<Coords> Houses { get; set; }
|
|
|
|
public KeyValuePair<List<IStep>, int> BestPath(ContentManager content, GarbageCollector collector, ICloneable[,] grid)
|
|
{
|
|
Houses = 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));
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
var r = SearchBfs(content, collector, grid, 0);
|
|
Console.WriteLine($"Counts : {count}");
|
|
if (r.Key == null) return new KeyValuePair<List<IStep>, int>(new List<IStep>(), 0);
|
|
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;
|
|
}
|
|
|
|
|
|
string Line(GarbageCollector collector, ICloneable [,] grid)
|
|
{
|
|
|
|
var s = "";
|
|
foreach (var can in collector.TrashContainers)
|
|
{
|
|
s += " " + can.TypeOfGarbage.GarbageType.ToString() + ":." + (int)can.FillPercent * 100;
|
|
}
|
|
|
|
|
|
|
|
for (int x = collector.Coords.X - 2; x <= collector.Coords.X + 2; x++)
|
|
{
|
|
|
|
for (int y = collector.Coords.Y - 2; y <= collector.Coords.Y + 2; y++)
|
|
{
|
|
var xoffset = x - (collector.Coords.X - 2);
|
|
var yoffset = y - (collector.Coords.Y - 2);
|
|
|
|
|
|
if (x >= 0 && y >= 0 && x < grid.GetLength(0) && y < grid.GetLength(1))
|
|
{
|
|
|
|
var cell = grid[x, y];
|
|
|
|
if (cell is Grass) s += " " + xoffset.ToString() + yoffset.ToString() + "grass";
|
|
if (cell is Road1) s += " " + xoffset.ToString() + yoffset.ToString() + "road1";
|
|
if (cell is Road2) s += " " + xoffset.ToString() + yoffset.ToString() + "road2";
|
|
if (cell is Dump) s += " " + xoffset.ToString() + yoffset.ToString() + (cell as Dump).TypeOfGarbage.GarbageType.ToString();
|
|
if (cell is House)
|
|
{
|
|
|
|
var h = (cell as House);
|
|
foreach (var can in h.TrashCans)
|
|
{
|
|
s += " " + xoffset.ToString() + yoffset.ToString() + can.TypeOfGarbage.GarbageType.ToString() + ":." + (int)can.FillPercent * 100;
|
|
}
|
|
}
|
|
if (cell is EmptyHouse) s += " " + xoffset.ToString() + yoffset.ToString() + "emptyHouse";
|
|
}
|
|
else
|
|
{
|
|
s += " " + xoffset.ToString() + yoffset.ToString() + "grass";
|
|
}
|
|
|
|
|
|
}
|
|
}
|
|
return "| " + s;
|
|
}
|
|
|
|
|
|
|
|
KeyValuePair<List<IStep>, int> SearchBfs(ContentManager content, GarbageCollector collector, ICloneable[,] grid, int length)
|
|
{
|
|
|
|
//Thread.Sleep(1);
|
|
|
|
|
|
var steps = new List<IStep>();
|
|
int count = 0;
|
|
|
|
while (true)
|
|
{
|
|
count++;
|
|
|
|
Thread.Sleep(5);
|
|
this.Collector.Coords = collector.Coords;
|
|
this.Collector.TrashContainers = collector.TrashContainers;
|
|
for (int x = 0; x < grid.GetLength(0); x++)
|
|
{
|
|
for (int y = 0; y < grid.GetLength(1); y++)
|
|
{
|
|
this.Grid[x, y] = grid[x, y];
|
|
}
|
|
}
|
|
|
|
if (Houses.All(c => (grid[c.X, c.Y] as IGarbageLocalization).TrashCans.All(j => j.FillPercent == 0.0))
|
|
&&
|
|
collector.TrashContainers.All(i => i.FillPercent == 0.0)
|
|
)
|
|
{
|
|
Console.WriteLine(count);
|
|
return new KeyValuePair<List<IStep>, int>(steps, count);
|
|
}
|
|
|
|
|
|
var possible = PossibleSteps(collector, grid);
|
|
|
|
if (possible.Count == 0)
|
|
{
|
|
for (int x = 0; x < grid.GetLength(0); x++)
|
|
{
|
|
for (int y = 0; y < grid.GetLength(1); y++)
|
|
{
|
|
if (grid[x, y] is Road2) grid[x, y] = new Road1(new Coords(x, y));
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
var mapped = possible.Select(x =>
|
|
{
|
|
using (var vw = new VW.VowpalWabbit($" -i garbage{x.ID}.model"))
|
|
{
|
|
var line = Line(collector, grid);
|
|
double result = vw.Predict(Line(collector, grid), VW.VowpalWabbitPredictionType.Scalar);
|
|
return new KeyValuePair<IStep, double>(x, result);
|
|
}
|
|
}).ToArray();
|
|
var sum = mapped.Aggregate(0.0, (a, b) => a + b.Value);
|
|
Random random = new Random();
|
|
var rnd = random.NextDouble() * sum;
|
|
|
|
|
|
double cumulative = 0.0;
|
|
for (int i = 0; i < mapped.Count(); i++)
|
|
{
|
|
cumulative += mapped[i].Value;
|
|
if (rnd <= cumulative)
|
|
{
|
|
var best = mapped[i].Key;
|
|
|
|
|
|
steps.Add(best);
|
|
|
|
best.Invoke(collector, grid);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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;
|
|
}
|
|
}
|
|
}
|
|
|