public void RunGen(StreamWriter str) { Func <int, string> outputFile = (gen) => Path.Combine(_outputFolder, $"output_{gen}.txt"); Func <int, string> inputFile = (gen) => Path.Combine(_outputFolder, $"input_{gen}.txt"); Func <int, string> linesFile = (gen) => Path.Combine(_outputFolder, $"lines_{gen}.txt"); Func <int, string> tmpFile = (gen) => Path.Combine(_outputFolder, $"tmp_{gen}.txt"); Func <int, string> tmpFileC = (gen) => Path.Combine(_outputFolder, $"tmpC_{gen}.txt"); var lastGen = Enumerable.Range(0, _generations).Select(x => (int?)x).LastOrDefault(x => File.Exists(inputFile(x.GetValueOrDefault()))); var parents = lastGen != null?File.ReadAllLines(inputFile(lastGen.Value)).Select(x => new Ai(x)).ToList() : Enumerable.Range(0, _population).Select((x, i) => GeneratePlayer(i, 0)).ToList(); File.WriteAllLines(inputFile(lastGen.GetValueOrDefault()), parents.Select(x => x.ToString())); var tmpParents = new List <Ai>(); if (File.Exists(tmpFile(lastGen.GetValueOrDefault()))) { tmpParents = File.ReadAllLines(tmpFile(lastGen.GetValueOrDefault())).Select(x => new Ai(x)).ToList(); } var tmpChildren = new List <Ai>(); if (File.Exists(tmpFileC(lastGen.GetValueOrDefault()))) { tmpChildren = File.ReadAllLines(tmpFileC(lastGen.GetValueOrDefault())).Select(x => new Ai(x)).ToList(); } _nextId = Math.Max(parents.Max(x => x.Id) + 1, tmpChildren.Max(x => x.Id) + 1); for (int generation = lastGen.GetValueOrDefault(); generation < _generations; generation++) { Func <Ai, int> clearedLinesSelector = ai => ai.PreviousGames.Select(x => x.Item2).Sum(); Func <Ai, int> playedBlocksSelector = ai => ai.PreviousGames.Select(x => x.Item1).Sum(); var generation1 = generation; Func <Ai, double> selector = x => clearedLinesSelector(x) + (generation1 - x.Generation) / (double)_generations; if (!File.Exists(linesFile(generation))) { GenerateInput.Generate(_inputsCount, (_inputSize /* * (generation + 1)*/), linesFile(generation)); } var games = File.ReadAllLines(linesFile(generation)); var inputs = games.Select(x => Enumerable.Range(0, x.Length) .Select(i => x.Substring(i, i + _aheadRead >= x.Length ? x.Length - i : _aheadRead)) .ToList()).ToList(); int counted = 0; if (!File.Exists(tmpFile(generation))) { File.Create(tmpFile(generation)).Dispose(); } foreach (var parent in parents) { if (counted >= tmpParents.Count) { parent.PreviousGames = new ConcurrentBag <Tuple <int, int, int> >(); foreach (var input in inputs) //Parallel.ForEach(inputs, input => { var grid = parent.StartNewGame(); parent.PlayMoreMoves(input, ref grid); } //); File.AppendAllLines(tmpFile(generation), new[] { parent.ToString() }); tmpParents.Add(parent); } var pl = tmpParents[counted]; Console.WriteLine($"{generation,5}_{pl.Id,5}: {playedBlocksSelector(pl),6}/{clearedLinesSelector(pl),6} [{pl.Generation,4}] ({++counted})"); } parents = tmpParents.OrderByDescending(selector).ToList(); LogString(str, "Parents:"); LogString(str, $"CL: {generation,5}: Avg: {parents.Select(x => clearedLinesSelector(x)).Average(),6}, Min: {parents.Select(x => clearedLinesSelector(x)).Min(),6}, Max: {parents.Select(x => clearedLinesSelector(x)).Max(),6}"); LogString(str, $"PB: {generation,5}: Avg: {parents.Select(x => playedBlocksSelector(x)).Average(),6}, Min: {parents.Select(x => playedBlocksSelector(x)).Min(),6}, Max: {parents.Select(x => playedBlocksSelector(x)).Max(),6}"); LogString(str, "\tRatio: " + parents.Select(x => playedBlocksSelector(x)).Max() / (double)parents.Select(x => clearedLinesSelector(x)).Max()); //var ordered = players.OrderByDescending(selector).ToList(); LogString(str, $"\t{parents[0].Id}: {playedBlocksSelector(parents[0])}/{clearedLinesSelector(parents[0])} [{parents[0].Generation}] - {string.Join(" ", parents[0].Factors.Select(x => $"{x:0.00000000}"))}"); //{ordered[0].GapsW:0.00000000} {ordered[0].JumpsW:0.00000000} {ordered[0].HeightsW:0.00000000} {ordered[0].FullRowsW:0.00000000}"); LogString(str, $"\t{parents[1].Id}: {playedBlocksSelector(parents[1])}/{clearedLinesSelector(parents[1])} [{parents[1].Generation}] - {string.Join(" ", parents[1].Factors.Select(x => $"{x:0.00000000}"))}"); //{ordered[1].GapsW:0.00000000} {ordered[1].JumpsW:0.00000000} {ordered[1].HeightsW:0.00000000} {ordered[1].FullRowsW:0.00000000}"); LogString(str, ""); File.WriteAllText(outputFile(generation), string.Join(Environment.NewLine, parents.Select(x => x.ToString()))); List <Ai> children = new List <Ai>(); for (int i = 0; i < parents.Count; i++) { for (int j = i + 1; j < parents.Count; j++) { children.Add(GenerateOffspring2(parents[i], parents[j], _nextId++, generation + 1, selector)); } } counted = 0; if (!File.Exists(tmpFileC(generation))) { File.Create(tmpFileC(generation)).Dispose(); } foreach (var child in children) { if (counted >= tmpChildren.Count) { child.PreviousGames = new ConcurrentBag <Tuple <int, int, int> >(); foreach (var input in inputs) //Parallel.ForEach(inputs, input => { var grid = child.StartNewGame(); child.PlayMoreMoves(input, ref grid); } //); File.AppendAllLines(tmpFileC(generation), new[] { child.ToString() }); tmpChildren.Add(child); } var pl = tmpChildren[counted]; Console.WriteLine($"{generation,5}_{pl.Id,5}: {playedBlocksSelector(pl),6}/{clearedLinesSelector(pl),6} [{pl.Generation,4}] ({++counted})"); } children = tmpChildren.OrderByDescending(selector).ToList(); LogString(str, ""); LogString(str, $"CL: {generation,5}: Avg: {children.Select(x => clearedLinesSelector(x)).Average(),6}, Min: {children.Select(x => clearedLinesSelector(x)).Min(),6}, Max: {children.Select(x => clearedLinesSelector(x)).Max(),6}"); LogString(str, $"PB: {generation,5}: Avg: {children.Select(x => playedBlocksSelector(x)).Average(),6}, Min: {children.Select(x => playedBlocksSelector(x)).Min(),6}, Max: {children.Select(x => playedBlocksSelector(x)).Max(),6}"); LogString(str, "\tRatio: " + children.Select(x => playedBlocksSelector(x)).Max() / (double)children.Select(x => clearedLinesSelector(x)).Max()); //var ordered = players.OrderByDescending(selector).ToList(); LogString(str, $"\t{children[0].Id}: {playedBlocksSelector(children[0])}/{clearedLinesSelector(children[0])} [{children[0].Generation}] - {string.Join(" ", children[0].Factors.Select(x => $"{x:0.00000000}"))}"); //{ordered[0].GapsW:0.00000000} {ordered[0].JumpsW:0.00000000} {ordered[0].HeightsW:0.00000000} {ordered[0].FullRowsW:0.00000000}"); LogString(str, $"\t{children[1].Id}: {playedBlocksSelector(children[1])}/{clearedLinesSelector(children[1])} [{children[1].Generation}] - {string.Join(" ", children[1].Factors.Select(x => $"{x:0.00000000}"))}"); //{ordered[1].GapsW:0.00000000} {ordered[1].JumpsW:0.00000000} {ordered[1].HeightsW:0.00000000} {ordered[1].FullRowsW:0.00000000}"); LogString(str, ""); File.AppendAllLines(outputFile(generation), new List <string> { "" }); File.AppendAllLines(outputFile(generation), children.Select(x => x.ToString())); parents = parents.Concat(children).OrderByDescending(selector).Take(_population).ToList(); //players = PrepareNextGeneration(players, generation + 1, selector); tmpParents.Clear(); tmpChildren.Clear(); File.WriteAllLines(inputFile(generation + 1), parents.Select(x => x.ToString())); } }
public void RunGeneration(StreamWriter str) { Func <Ai, int> playedBlocksSelector = ai => ai.PreviousGames.Select(x => x.Item1).Sum(); //ai.PreviousGames.Skip(ai.PreviousGames.Count - _inputsCount).Select(x => x.Item1).Sum(); Func <Ai, int> clearedLinesSelector = ai => ai.PreviousGames.Select(x => x.Item2).Sum(); //ai.PreviousGames.Skip(ai.PreviousGames.Count - _inputsCount).Select(x => x.Item2).Sum(); Func <Ai, int> maxHeightSelector = ai => ai.PreviousGames.Select(x => x.Item3).Max(); //ai.PreviousGames.Skip(ai.PreviousGames.Count - _inputsCount).Select(x => x.Item2).Sum(); Func <Ai, int> maxHeightsSumSelector = ai => ai.PreviousGames.Select(x => x.Item3).Sum(); //ai.PreviousGames.Skip(ai.PreviousGames.Count - _inputsCount).Select(x => x.Item2).Sum(); //var players = Enumerable.Range(0, _population).Select((x, i) => GeneratePlayer(i, 0)).ToList(); var lastGen = Enumerable.Range(0, _generations).Select(x => (int?)x).LastOrDefault(x => File.Exists(Path.Combine(_outputFolder, $"input_{x}.txt"))); var inputFileName = Path.Combine(_outputFolder, $"input_{lastGen ?? 0}.txt"); var players = lastGen != null?File.ReadAllLines(inputFileName).Select(x => new Ai(x)).ToList() : Enumerable.Range(0, _population).Select((x, i) => GeneratePlayer(i, 0)).ToList(); File.WriteAllLines(inputFileName, players.Select(x => x.ToString())); List <Ai> tmpPlayers = new List <Ai>(); string tmpFileName = Path.Combine(_outputFolder, $"tmp_{lastGen}.txt"); if (File.Exists(tmpFileName)) { tmpPlayers = File.ReadAllLines(tmpFileName).Select(x => new Ai(x)).ToList(); } for (int generation = lastGen ?? 0; generation < _generations; generation++) { var generation1 = generation; Func <Ai, double> selector = x => /*playedBlocksSelector(x) * 2 +*/ clearedLinesSelector(x) + (generation1 - x.Generation) / (double)_generations; // Func<Ai, double> selector = // x => // -maxHeightSelector(x) - (maxHeightsSumSelector(x)/(_w*_h*_inputsCount)) - // 2.5/(playedBlocksSelector(x)/clearedLinesSelector(x)); string fileName = Path.Combine(_outputFolder, $"inputsGen_{generation}.txt"); if (!File.Exists(fileName)) { GenerateInput.Generate(_inputsCount, (_inputSize /* * (generation + 1)*/), fileName); } var games = File.ReadAllLines(fileName); var inputs = games.Select( x => Enumerable.Range(0, x.Length) .Select(i => x.Substring(i, i + _aheadRead >= x.Length ? x.Length - i : _aheadRead)) .ToList()).ToList(); int counted = 0; tmpFileName = Path.Combine(_outputFolder, $"tmp_{generation}.txt"); if (!File.Exists(tmpFileName)) { File.Create(tmpFileName).Dispose(); } foreach (var player in players) //Parallel.ForEach(players, player => { if (counted >= tmpPlayers.Count) { player.PreviousGames = new ConcurrentBag <Tuple <int, int, int> >(); foreach (var input in inputs) //Parallel.ForEach(inputs, input => { var grid = player.StartNewGame(); player.PlayMoreMoves(input, ref grid); } //); //player.EndRound(_inputsCount); File.AppendAllLines(tmpFileName, new[] { player.ToString() }); tmpPlayers.Add(player); } var pl = tmpPlayers[counted]; //File.AppendAllLines("progress.tmp",new []{player.ToString()}); Console.WriteLine( $"{generation,5}_{pl.Id,5}: {playedBlocksSelector(pl),6}/{clearedLinesSelector(pl),6}/{maxHeightSelector(pl),6} [{pl.Generation,4}] ({++counted})"); } players = tmpPlayers; //); LogString(str, ""); LogString(str, $"CL: {generation,5}: Avg: {players.Select(x => clearedLinesSelector(x)).Average(),6}, Min: {players.Select(x => clearedLinesSelector(x)).Min(),6}, Max: {players.Select(x => clearedLinesSelector(x)).Max(),6}"); LogString(str, $"PB: {generation,5}: Avg: {players.Select(x => playedBlocksSelector(x)).Average(),6}, Min: {players.Select(x => playedBlocksSelector(x)).Min(),6}, Max: {players.Select(x => playedBlocksSelector(x)).Max(),6}"); LogString(str, $"MH: {generation,5}: Avg: {players.Select(x => maxHeightSelector(x)).Average(),6}, Min: {players.Select(x => maxHeightSelector(x)).Min(),6}, Max: {players.Select(x => maxHeightSelector(x)).Max(),6}"); LogString(str, "\tRatio: " + players.Select(x => playedBlocksSelector(x)).Max() / (double)players.Select(x => clearedLinesSelector(x)).Max()); var ordered = players.OrderByDescending(selector).ToList(); LogString(str, $"\t{ordered[0].Id}: {playedBlocksSelector(ordered[0])}/{clearedLinesSelector(ordered[0])}/{maxHeightSelector(ordered[0])} [{ordered[0].Generation}] - {string.Join(" ", ordered[0].Factors.Select(x => $"{x:0.00000000}"))}"); //{ordered[0].GapsW:0.00000000} {ordered[0].JumpsW:0.00000000} {ordered[0].HeightsW:0.00000000} {ordered[0].FullRowsW:0.00000000}"); LogString(str, $"\t{ordered[1].Id}: {playedBlocksSelector(ordered[1])}/{clearedLinesSelector(ordered[1])}/{maxHeightSelector(ordered[1])} [{ordered[1].Generation}] - {string.Join(" ", ordered[1].Factors.Select(x => $"{x:0.00000000}"))}"); //{ordered[1].GapsW:0.00000000} {ordered[1].JumpsW:0.00000000} {ordered[1].HeightsW:0.00000000} {ordered[1].FullRowsW:0.00000000}"); LogString(str, ""); File.WriteAllText(GetGenerationFilePath(generation), string.Join(Environment.NewLine, ordered.Select(x => x.ToString()))); players = PrepareNextGeneration(players, generation + 1, selector); tmpPlayers.Clear(); File.WriteAllLines(Path.Combine(_outputFolder, $"input_{generation+1}.txt"), players.Select(x => x.ToString())); } }