/// <summary> /// Called internally to process the journey optimisation queue. /// </summary> private void OptimisationLoop() { var detailedExportContext = JsonConvert.CreateExportContext(); var summaryExportContext = JsonConvert.CreateExportContext(); detailedExportContext.Register(new CritterExporter(CritterExporter.ExportType.Expanded)); summaryExportContext.Register(new CritterExporter(CritterExporter.ExportType.Summary)); { // try while (!this.cTokenSource.IsCancellationRequested) { string jUuid = string.Empty; Run run = null; //try { this.currentIteration = 0; this.state = OptimiserState.Waiting; if (this.bc.Count == 0 && this.exitThreadWhenQueueEmpty) { return; } this.Save(); jUuid = this.bc.Take(this.cTokenSource.Token); this.state = OptimiserState.Optimising; run = new Run(); var journey = this.journeyManager.GetJourney(jUuid); this.currentJourney = journey; run.JourneyUuid = journey.Uuid; run.TimeStarted = DateTime.Now; var planner = new MoeaJourneyPlanner(journey.Properties); var results = new List<Result>(journey.Properties.MaxIterations); this.maxIterations = journey.Properties.MaxIterations; planner.Start(); for (int i = 0; i < journey.Properties.MaxIterations; i++) { this.currentIteration++; planner.SolveStep(); results.Add((Result)planner.IterationResult.Clone()); while (this.paused) { Thread.Sleep(100); } // results.Add(planner.re); if (this.cTokenSource.IsCancellationRequested) { break; } } run.TimeFinished = DateTime.Now; var maxTT = results.Max(r => r.Population.Max(p => p.Fitness.TotalTravelTime)).TotalSeconds; var minTT = results.Min(r => r.Population.Min(p => p.Fitness.TotalTravelTime)).TotalSeconds; var maxJT = results.Max(r => r.Population.Max(p => p.Fitness.TotalJourneyTime)).TotalSeconds; var minJT = results.Min(r => r.Population.Min(p => p.Fitness.TotalJourneyTime)).TotalSeconds; var maxCh = results.Max(r => r.Population.Max(p => p.Fitness.Changes)); var minCh = results.Min(r => r.Population.Min(p => p.Fitness.Changes)); foreach (var result in results) { foreach (var p in result.Population) { p.Fitness.NormalisedChanges = Math.Min( 1.0f, p.Fitness.Changes / (double)(maxCh - minCh)); p.Fitness.NormalisedJourneyTime = Math.Max( 1.0f, p.Fitness.TotalJourneyTime.TotalSeconds / (maxJT - minJT)); p.Fitness.NormalisedTravelTime = Math.Max( 1.0f, p.Fitness.TotalTravelTime.TotalSeconds / (maxTT - minTT)); } } if (!this.cTokenSource.IsCancellationRequested) { lock (journey.RunUuids) { // TODO: Make this more efficient/better coded var newList = new List<string>(journey.RunUuids); newList.Add(run.Uuid); journey.RunUuids = newList.ToArray(); string dir = this.directories[1] + "/" + journey.Uuid + "/"; Directory.CreateDirectory(dir + run.Uuid); using (var resultWriter = new StreamWriter(dir + run.Uuid + "/results.csv", false)) { resultWriter.Write("Iteration,Hypervolume,Cardinality,"); foreach (var p in Enum.GetValues(typeof(FitnessParameter))) { resultWriter.Write("{0}, ", p); } resultWriter.WriteLine(); for (int i = 0; i < results.Count; i++) { using ( var writer = new StreamWriter(dir + run.Uuid + "/iteration." + i + ".json")) { results[i].Hypervolume = 0.0; /*results[i].Population.CalculateHyperVolume( journey.Properties.Objectives, new double[journey.Properties.Objectives.Length]);*/ var grouped = from p in results[i].Population group p by p.Route into g select g; var candidates = new List<Critter>(); foreach (var g in grouped) { TimeSpan minTime = TimeSpan.MaxValue; Critter minCrit = null; foreach (var critter in g) { if (critter.Fitness.TotalJourneyTime < minTime) { minTime = critter.Fitness.TotalJourneyTime; minCrit = critter; } } candidates.Add(minCrit); } var groupedResult = (Result)results[i].Clone(true); groupedResult.Population = new Population(candidates.OrderBy(c => c.Fitness.TotalJourneyTime)); detailedExportContext.Export(groupedResult, new JsonTextWriter(writer)); resultWriter.Write( "{0}, {1}, {2}, ", i, results[i].Hypervolume, results[i].Cardinality); foreach (var p in Enum.GetValues(typeof(FitnessParameter))) { resultWriter.Write( "{0},", results[i].Population.Average(c => c.Fitness[(FitnessParameter)p])); } resultWriter.WriteLine(); } // For the last result entry, Save simplified file. if (i != results.Count - 1) { continue; } using (var writer = new StreamWriter(dir + run.Uuid + "/simple.json")) { using (var jsonWriter = new JsonTextWriter(writer)) { var grouped = from p in results[i].Population group p by p.Route into g select g; var candidates = new List<Critter>(); foreach (var g in grouped) { TimeSpan minTime = TimeSpan.MaxValue; Critter minCrit = null; foreach (var critter in g) { if (critter.Fitness.TotalJourneyTime < minTime) { minTime = critter.Fitness.TotalJourneyTime; minCrit = critter; } } candidates.Add(minCrit); } summaryExportContext.Export(candidates.OrderBy(c => c.Fitness.TotalJourneyTime), jsonWriter); } } } using (var writer = new StreamWriter(dir + run.Uuid + ".json")) { detailedExportContext.Export(run, new JsonTextWriter(writer)); } results.Clear(); } } this.journeyManager.Save(); } this.currentJourney = null; this.currentIteration = 0; this.maxIterations = 0; } /* catch (Exception e) { StreamWriter logWriter = new StreamWriter("Log.txt"); logWriter.WriteLine( "Exception: {0} jUUID: {1}, rUUID{2}, ST {3}\n\n", e.Message, jUuid, (run ?? new Run { ErrorCode = -1, JourneyUuid = jUuid }).Uuid, e.StackTrace); logWriter.Close(); // throw; } */ } } /* catch (Exception e) { //this.thrownException = e; throw; } finally { this.state = OptimiserState.Idle; } * */ }
/// <summary> /// Pauses the current optimisation run at the next available oportunity. /// </summary> public void Pause() { if (this.state == OptimiserState.Optimising) { this.paused = true; this.state = OptimiserState.Paused; } }
/// <summary> /// Resumes the current optimisation run. /// </summary> public void Resume() { if (this.state == OptimiserState.Paused) { this.paused = false; this.state = OptimiserState.Optimising; } }
/// <summary> /// Cancels the current job and halts the optimisation. /// </summary> public void Cancel() { this.paused = false; this.cTokenSource.Cancel(); this.state = OptimiserState.Cancelling; }