Changeset 13551 for branches/PerformanceComparison/HeuristicLab.OptimizationExpertSystem/3.3/ExpertSystem.cs
- Timestamp:
- 01/19/16 08:49:23 (9 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/PerformanceComparison/HeuristicLab.OptimizationExpertSystem/3.3/ExpertSystem.cs
r13485 r13551 28 28 using System.Threading.Tasks; 29 29 using HeuristicLab.Analysis; 30 using HeuristicLab.Collections; 30 31 using HeuristicLab.Common; 31 32 using HeuristicLab.Common.Resources; … … 36 37 using HeuristicLab.Persistence.Default.CompositeSerializers.Storable; 37 38 using HeuristicLab.Persistence.Default.Xml; 39 using RunCreationClient = HeuristicLab.Clients.OKB.RunCreation.RunCreationClient; 40 using SingleObjectiveOKBProblem = HeuristicLab.Clients.OKB.RunCreation.SingleObjectiveOKBProblem; 38 41 39 42 namespace HeuristicLab.OptimizationExpertSystem { … … 68 71 69 72 [Storable] 70 private ItemList<IAlgorithm> algorithmInstances;71 public ItemList<IAlgorithm> AlgorithmInstances{72 get { return algorithmInstances; }73 private RunCollection knowledgeBase; 74 public RunCollection KnowledgeBase { 75 get { return knowledgeBase; } 73 76 set { 74 if (algorithmInstances == value) return; 75 algorithmInstances = value; 76 OnPropertyChanged("AlgorithmInstances"); 77 // TODO: Attach event handlers 78 } 79 } 80 81 [Storable] 82 private ISingleObjectiveHeuristicOptimizationProblem problem; 83 public ISingleObjectiveHeuristicOptimizationProblem Problem { 77 if (knowledgeBase == value) return; 78 knowledgeBase = value; 79 OnPropertyChanged("KnowledgeBase"); 80 } 81 } 82 83 [Storable] 84 private SingleObjectiveOKBProblem problem; 85 public SingleObjectiveOKBProblem Problem { 84 86 get { return problem; } 85 87 set { … … 109 111 } 110 112 113 [Storable] 114 private BidirectionalLookup<long, IRun> algorithmId2RunMapping; 115 [Storable] 116 private BidirectionalDictionary<long, IAlgorithm> algorithmId2AlgorithmInstanceMapping; 117 111 118 private bool Maximization { 112 get { return Problem != null && ((IValueParameter<BoolValue>)Problem.MaximizationParameter).Value.Value; } 119 get { 120 return Problem != null && Problem.ProblemId >= 0 && ((IValueParameter<BoolValue>)Problem.MaximizationParameter).Value.Value; 121 } 113 122 } 114 123 … … 118 127 : base(original, cloner) { 119 128 runs = cloner.Clone(original.runs); 120 algorithmInstances = cloner.Clone(original.algorithmInstances); 121 problem = cloner.Clone(original.problem); 129 knowledgeBase = cloner.Clone(original.knowledgeBase); 122 130 suggestedInstances = cloner.Clone(original.suggestedInstances); 123 131 readOnlySuggestedInstances = suggestedInstances.AsReadOnly(); 124 132 problemInstances = cloner.Clone(original.problemInstances); 133 problem = cloner.Clone(original.problem); 134 algorithmId2RunMapping = new BidirectionalLookup<long, IRun>(); 135 foreach (var kvp in original.algorithmId2RunMapping.FirstEnumerable) { 136 algorithmId2RunMapping.AddRangeFirst(kvp.Key, kvp.Select(cloner.Clone)); 137 } 138 algorithmId2AlgorithmInstanceMapping = new BidirectionalDictionary<long, IAlgorithm>(); 139 foreach (var kvp in original.algorithmId2AlgorithmInstanceMapping) { 140 algorithmId2AlgorithmInstanceMapping.Add(kvp.Key, cloner.Clone(kvp.Value)); 141 } 125 142 RegisterEventHandlers(); 126 143 } … … 129 146 Description = ItemDescription; 130 147 runs = new RunCollection(); 131 algorithmInstances = new ItemList<IAlgorithm>();148 knowledgeBase = new RunCollection(); 132 149 suggestedInstances = new ItemList<IAlgorithm>(); 133 150 readOnlySuggestedInstances = suggestedInstances.AsReadOnly(); 134 151 problemInstances = new RunCollection(); 152 problem = new SingleObjectiveOKBProblem(); 153 algorithmId2RunMapping = new BidirectionalLookup<long, IRun>(); 154 algorithmId2AlgorithmInstanceMapping = new BidirectionalDictionary<long, IAlgorithm>(); 135 155 RegisterEventHandlers(); 156 } 157 158 private void ProblemOnProblemChanged(object sender, EventArgs eventArgs) { 159 if (Problem == null) return; 136 160 } 137 161 … … 147 171 148 172 private void RegisterEventHandlers() { 173 problem.ProblemChanged += ProblemOnProblemChanged; 149 174 runs.CollectionReset += InformationChanged; 150 175 runs.ItemsAdded += InformationChanged; … … 152 177 runs.Reset += InformationChanged; 153 178 runs.UpdateOfRunsInProgressChanged += InformationChanged; 154 algorithmInstances.CollectionReset += InformationChanged;155 algorithmInstances.ItemsAdded += InformationChanged;156 algorithmInstances.ItemsRemoved += InformationChanged;179 knowledgeBase.CollectionReset += InformationChanged; 180 knowledgeBase.ItemsAdded += InformationChanged; 181 knowledgeBase.ItemsRemoved += InformationChanged; 157 182 } 158 183 … … 181 206 alglib.pcabuildbasis(ds, instanceCounter, flaValues.Count, out info, out s2, out v); 182 207 183 var algInstRunDict = AlgorithmInstances.SelectMany(x => x.Runs)184 .Where(x => x.Parameters.ContainsKey("Problem Name") && x.Parameters["Problem Name"] is StringValue)185 .GroupBy(x => ((StringValue)x.Parameters["Problem Name"]).Value)186 .ToDictionary(x => x.Key, x => x.GroupBy(y => ((StringValue)y.Parameters["Algorithm Name"]).Value)187 .ToDictionary(y => y.Key, y => y.ToList()));188 208 ProblemInstances.UpdateOfRunsInProgress = true; 189 209 try { 190 210 instanceCounter = 0; 191 211 foreach (var instance in ProblemInstances) { 192 IItem probNameParam;193 if (!instance.Parameters.TryGetValue("Problem Name", out probNameParam)) continue;194 var probInstanceName = ((StringValue)probNameParam).Value;195 196 212 double x = 0, y = 0; 197 213 for (var feature = 0; feature < flaValues.Count; feature++) { … … 208 224 209 225 instanceCounter++; 210 226 } 227 } finally { ProblemInstances.UpdateOfRunsInProgress = false; } 228 } 229 230 private static readonly HashSet<string> InterestingValueNames = new HashSet<string>() { 231 "QualityPerEvaluations", "Problem Name", "Problem Type", "Algorithm Name", "Algorithm Type", "Maximization", "BestKnownQuality" 232 }; 233 234 public async void UpdateKnowledgeBaseAsync(IProgress progress) { 235 progress.Start("Updating Knowledge Base from OKB"); 236 await Task.Factory.StartNew(() => { DoUpdateKnowledgeBase(progress); }, TaskCreationOptions.LongRunning); 237 } 238 239 public void UpdateKnowledgeBase() { 240 DoUpdateKnowledgeBase(new Progress(string.Empty, ProgressState.Started)); 241 } 242 243 private void DoUpdateKnowledgeBase(IProgress progress) { 244 var queryClient = Clients.OKB.Query.QueryClient.Instance; 245 var adminClient = Clients.OKB.Administration.AdministrationClient.Instance; 246 try { 247 progress.Status = "Downloading run information..."; 248 progress.ProgressValue = 0; 249 // FIXME: How to tell if refresh is necessary? 250 queryClient.Refresh(); 251 progress.ProgressValue = 0.5; 252 progress.Status = "Downloading algorithm and problem instance information..."; 253 // FIXME: How to tell if refresh is necessary? 254 adminClient.Refresh(); 255 256 var probInstance = adminClient.Problems.SingleOrDefault(x => x.Id == Problem.ProblemId); 257 if (probInstance == null) throw new InvalidOperationException("The chosen problem instance cannot be found in the OKB."); 258 var probClassId = probInstance.ProblemClassId; 259 260 var problemClassFilter = (Clients.OKB.Query.StringComparisonAvailableValuesFilter)queryClient.Filters.Single(x => x.Label == "Problem Class Name"); 261 problemClassFilter.Value = adminClient.ProblemClasses.Single(x => x.Id == probClassId).Name; 262 263 progress.Status = "Downloading problem instances..."; 264 progress.ProgressValue = 0; 265 var p = 0; 266 ProblemInstances.UpdateOfRunsInProgress = true; 267 ProblemInstances.Clear(); 268 var totalProblems = adminClient.Problems.Count(x => x.ProblemClassId == probClassId); 269 foreach (var problInst in adminClient.Problems.Where(x => x.ProblemClassId == probClassId)) { 270 progress.Status = string.Format("Downloading problem {0} (okb-id: {1})....", problInst.Name, problInst.Id); 271 var data = Clients.OKB.Administration.AdministrationClient.GetProblemData(problInst.Id); 272 if (data != null) { 273 using (var stream = new MemoryStream(data)) { 274 try { 275 var prob = (IProblem)XmlParser.Deserialize<IContent>(stream); 276 var probRun = new Run() { Name = prob.Name }; 277 prob.CollectParameterValues(probRun.Parameters); 278 progress.Status += Environment.NewLine + "Downloading characteristics..."; 279 foreach (var v in RunCreationClient.GetCharacteristicValues(problInst.Id)) { 280 probRun.Results.Add("Characteristic." + v.Name, RunCreationClient.Instance.ConvertToItem(v)); 281 } 282 ProblemInstances.Add(probRun); 283 } catch { } 284 stream.Close(); 285 } 286 } 287 p++; 288 progress.ProgressValue = p / (double)totalProblems; 289 } 290 291 algorithmId2AlgorithmInstanceMapping.Clear(); 292 progress.Status = "Downloading algorithm instances..."; 293 progress.ProgressValue = 0; 294 p = 0; 295 foreach (var algInst in adminClient.Algorithms) { 296 progress.Status = string.Format("Downloading algorithm {0} (okb-id: {1})...", algInst.Name, algInst.Id); 297 var data = Clients.OKB.Administration.AdministrationClient.GetAlgorithmData(algInst.Id); 298 if (data != null) { 299 using (var stream = new MemoryStream(data)) { 300 try { 301 var alg = (IAlgorithm)XmlParser.Deserialize<IContent>(stream); 302 algorithmId2AlgorithmInstanceMapping.Add(algInst.Id, alg); 303 } catch { } 304 stream.Close(); 305 } 306 } 307 p++; 308 progress.ProgressValue = p / (double)adminClient.Algorithms.Count; 309 } 310 311 var interestingValues = queryClient.ValueNames.Where(x => InterestingValueNames.Contains(x.Name)).ToList(); 312 313 progress.Status = "Obtaining number of runs..."; 314 progress.ProgressValue = 0; 315 p = 0; 316 var count = queryClient.GetNumberOfRuns(problemClassFilter); 317 if (count == 0) return; 318 319 var runIds = queryClient.GetRunIds(problemClassFilter).ToList(); 320 var conversions = new List<Task>(); 321 var runList = new List<IRun>(); 322 while (p < count) { 323 var nextIds = runIds.Skip(p).Take(500).ToList(); 324 progress.Status = string.Format("Downloading runs {0} to {1} of {2}...", p, p + nextIds.Count, count); 325 var okbRuns = queryClient.GetRunsWithValues(nextIds, true, interestingValues); 326 conversions.Add(Task.Factory.StartNew(() => { 327 var hlRuns = okbRuns.AsParallel().Select(x => new { AlgorithmId = x.Algorithm.Id, Run = queryClient.ConvertToOptimizationRun(x) }).ToList(); 328 lock (runList) { 329 foreach (var r in hlRuns) { 330 algorithmId2RunMapping.Add(r.AlgorithmId, r.Run); 331 runList.Add(r.Run); 332 } 333 } 334 })); 335 p += nextIds.Count; 336 progress.ProgressValue = p / (double)count; 337 } 338 Task.WaitAll(conversions.ToArray()); 339 340 progress.Status = "Finishing..."; 341 var algInstRunDict = runList.Where(x => x.Parameters.ContainsKey("Problem Name") && x.Parameters["Problem Name"] is StringValue) 342 .GroupBy(x => ((StringValue)x.Parameters["Problem Name"]).Value) 343 .ToDictionary(x => x.Key, x => x.GroupBy(y => ((StringValue)y.Parameters["Algorithm Name"]).Value) 344 .ToDictionary(y => y.Key, y => y.ToList())); 345 346 foreach (var instance in ProblemInstances) { 347 IItem probNameParam; 348 if (!instance.Parameters.TryGetValue("Problem Name", out probNameParam)) continue; 349 350 var probInstanceName = ((StringValue)probNameParam).Value; 211 351 var bkQuality = ((DoubleValue)instance.Parameters["BestKnownQuality"]).Value; 212 352 var maximization = ((BoolValue)instance.Parameters["Maximization"]).Value; … … 219 359 var result = ExpectedRuntimeHelper.CalculateErt(kvp.Value, "QualityPerEvaluations", bkQuality * target, maximization); 220 360 var resultName = algInstanceName + "@" + ((target - 1) * 100) + "%"; 361 IItem item; 221 362 if (instance.Results.TryGetValue(resultName, out item)) { 222 363 ((DoubleValue)item).Value = Math.Log10(result.ExpectedRuntime); … … 225 366 } 226 367 } 227 } finally { ProblemInstances.UpdateOfRunsInProgress = false; } 228 } 229 230 private static readonly HashSet<string> InterestingValueNames = new HashSet<string>() { 231 "QualityPerEvaluations", "Problem Name", "Problem Type", "Algorithm Name", "Algorithm Type", "Maximization" 232 }; 233 234 public async void UpdateKnowledgeBaseAsync(IProgress progress) { 235 progress.Start("Updating Knowledge Base from OKB"); 236 await Task.Factory.StartNew(() => { DoUpdateKnowledgeBase(progress); }, TaskCreationOptions.LongRunning); 237 } 238 239 public void UpdateKnowledgeBase() { 240 DoUpdateKnowledgeBase(new Progress(string.Empty, ProgressState.Started)); 241 } 242 243 private void DoUpdateKnowledgeBase(IProgress progress) { 244 var queryClient = Clients.OKB.Query.QueryClient.Instance; 245 var adminClient = Clients.OKB.Administration.AdministrationClient.Instance; 246 try { 247 progress.Status = "Refreshing query client..."; 248 queryClient.Refresh(); 249 var interestingValues = queryClient.ValueNames.Where(x => InterestingValueNames.Contains(x.Name)).ToList(); 250 251 var problemTypeFilter = (Clients.OKB.Query.StringComparisonAvailableValuesFilter)queryClient.Filters.Single(x => x.Label == "Problem Data Type Name"); 252 problemTypeFilter.Value = Problem.GetType().Name; 253 254 progress.Status = "Obtaining number of runs..."; 255 var count = queryClient.GetNumberOfRuns(problemTypeFilter); 256 if (count == 0) return; 257 258 var runIds = queryClient.GetRunIds(problemTypeFilter).ToList(); 259 adminClient.Refresh(); 260 var i = 0; 261 var conversions = new List<Task>(); 262 var runGroup = new Dictionary<Tuple<long, string>, List<IRun>>(); 263 while (i < count) { 264 var nextIds = runIds.Skip(i).Take(500).ToList(); 265 progress.Status = string.Format("Downloading runs {0} to {1} of {2}...", i, i + nextIds.Count, count); 266 var okbRuns = queryClient.GetRunsWithValues(nextIds, true, interestingValues); 267 conversions.Add(Task.Factory.StartNew(() => { 268 var hlRuns = okbRuns.AsParallel().Select(x => new { Id = x.Algorithm.Id, Name = x.Algorithm.Name, Run = queryClient.ConvertToOptimizationRun(x) }) 269 .GroupBy(x => Tuple.Create(x.Id, x.Name)).ToList(); 270 lock (runGroup) { 271 foreach (var hr in hlRuns) { 272 List<IRun> runList; 273 if (!runGroup.TryGetValue(hr.Key, out runList)) { 274 runList = new List<IRun>(); 275 runGroup[hr.Key] = runList; 276 } 277 runList.AddRange(hr.Select(x => x.Run)); 278 } 279 } 280 })); 281 i += nextIds.Count; 282 progress.ProgressValue = 0.8 * (i / (double)count); 283 } 284 Task.WaitAll(conversions.ToArray()); 285 var list = new ItemList<IAlgorithm>(); 286 i = 0; 287 foreach (var rGroup in runGroup) { 288 progress.Status = string.Format("Downloading algorithm {0}...", rGroup.Key.Item2); 289 var data = Clients.OKB.Administration.AdministrationClient.GetAlgorithmData(rGroup.Key.Item1); 290 if (data != null) { 291 using (var stream = new MemoryStream(data)) { 292 try { 293 var alg = (IAlgorithm)XmlParser.Deserialize<IContent>(stream); 294 alg.Runs.AddRange(rGroup.Value); 295 list.Add(alg); 296 } catch (Exception) { } 297 stream.Close(); 298 } 299 } 300 i++; 301 progress.ProgressValue = 0.8 + 0.2 * (i / (double)runGroup.Count); 302 } 303 AlgorithmInstances = list; 304 } finally { progress.Finish(); } 368 KnowledgeBase = new RunCollection(runList); 369 } finally { progress.Finish(); ProblemInstances.UpdateOfRunsInProgress = false; } 305 370 } 306 371 … … 308 373 if (Problem == null) return; 309 374 var instances = new SortedList<double, IAlgorithm>(); 310 foreach (var instance in algorithmInstances) { 311 var relevantRuns = instance.Runs.Where(x => ((StringValue)x.Parameters["Problem Type"]).Value == Problem.GetType().Name); 375 foreach (var relevantRuns in knowledgeBase.GroupBy(x => x.Algorithm)) { 312 376 var avgQuality = 0.0; 313 377 var counter = 0; … … 320 384 } 321 385 avgQuality /= counter; 322 instances.Add(avgQuality, instance);386 instances.Add(avgQuality, relevantRuns.Key); 323 387 } 324 388 325 389 suggestedInstances.Clear(); 326 var instanceLadder = instances.Select(x => x.Value);390 var instanceLadder = instances.Select(x => (IAlgorithm)x.Value.Clone()); 327 391 suggestedInstances.AddRange(Maximization ? instanceLadder.Reverse() : instanceLadder); 328 392 }
Note: See TracChangeset
for help on using the changeset viewer.