/// <summary> /// Delegates the generation to the underlying view models. /// Displays the generated content using the unity objects /// </summary> /// <param name="finishAction">The action to invoke when the generation is completed.</param> /// <param name="generationStartAction">The action to invoke when a generation starts.</param> /// <param name="generationEndAction">The action to invoke when a generation ends.</param> /// <param name="cancellationToken">The cancellation token, used to cancel the generation.</param> internal async void GenerateAsync( Action finishAction, OnGenerationStart generationStartAction, OnGenerationEnd generationEndAction, CancellationToken cancellationToken) { Reset(); _finishedGenerations = 0; _onGenerationStart = generationStartAction; _onGenerationEnd = generationEndAction; // Invokes the finish action void OnGenerationFinish() => finishAction?.Invoke(); // Update the cancellation token of the view models terrainViewModel.CancelToken = cancellationToken; cityViewModel.CancelToken = cancellationToken; try { // Generate the terrain var(terrainMesh, terrainTexture) = await Task.Run(() => terrainViewModel.Generate(), cancellationToken); if (cancellationToken.IsCancellationRequested || terrainMesh == null || terrainTexture == null) { // Either the task was cancelled or a terrain value is null, abort. OnGenerationFinish(); return; } // Update component data _meshFilter.sharedMesh = terrainMesh; _meshCollider.sharedMesh = terrainMesh; _meshRenderer.sharedMaterial.mainTexture = terrainTexture; // Update the model's terrain data _model.TerrainTexture = terrainTexture; _model.TerrainHeightMap = _meshFilter.sharedMesh.HeightMap(); _model.TerrainOffset = _meshFilter.transform.position; // Generate a city _model.City = await Task.Run(() => cityViewModel.Generate(), cancellationToken); } catch (TaskCanceledException) { // A task was canceled, abort OnGenerationFinish(); return; } if (cancellationToken.IsCancellationRequested || _model.City == null) { // Either the task was canceled or the city is not valid, abort. OnGenerationFinish(); return; } // Create game objects based on the world data (terrain and city elements) CreateGameObjects(cancellationToken); // Invoke the finish action OnGenerationFinish(); }
public Ann Train(int maxGenerations, int generationSize, double?errorThreshold, int mutationRate, int mutationRolls, bool waitForFlag, double[][] inputs, double[][] expectedOutputs, Crossover.CrossoverOperation crossoverOperation, ActivationFunction.ActivationMethod activationMethod) { Ann[] generation = new Ann[generationSize]; int inputCount = inputs[0].Length; int outputCount = expectedOutputs[0].Length; for (int generationId = 0; generationId < maxGenerations; generationId++) { if (generationId == 0) { for (int startingIndividual = 0; startingIndividual < generationSize; startingIndividual++) { Ann ann = new Ann(inputCount, outputCount, activationMethod); double error = CalculateError(ann, inputs, expectedOutputs); ann.Error = error; generation[startingIndividual] = ann; } } else { Ann parentA = generation[0]; Ann parentB = generation[1]; for (int newIndividual = 0; newIndividual < generationSize; newIndividual++) { generation = generation.OrderByDescending(x => x.Error).ToArray(); Ann child = crossoverOperation.Invoke(parentA, parentB); Mutations.RollToCauseRandomMutation(child, mutationRate, mutationRolls); double error = CalculateError(child, inputs, expectedOutputs); child.Error = error; if (child.Error < generation[0].Error) { generation[0] = child; } } } generation.ToList().ForEach(x => { x.Error = CalculateError(x, inputs, expectedOutputs); x.Generation = generationId; }); generation = generation.OrderBy(x => x.Error).ToArray(); if (waitForFlag) { waitFlag = true; OnGenerationEnd?.Invoke(generation[0]); while (waitFlag) { } } else { OnGenerationEnd?.Invoke(generation[0]); } if (errorThreshold != null && generation[0].Error < errorThreshold) { return(generation[0]); } } return(generation[0]); }