Free cookie consent management tool by TermsFeed Policy Generator

Ignore:
Timestamp:
01/19/16 08:49:23 (8 years ago)
Author:
abeham
Message:

#2457: Added characteristic calculator for qap and adapted expert system view

File:
1 edited

Legend:

Unmodified
Added
Removed
  • branches/PerformanceComparison/HeuristicLab.OptimizationExpertSystem/3.3/ExpertSystem.cs

    r13485 r13551  
    2828using System.Threading.Tasks;
    2929using HeuristicLab.Analysis;
     30using HeuristicLab.Collections;
    3031using HeuristicLab.Common;
    3132using HeuristicLab.Common.Resources;
     
    3637using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
    3738using HeuristicLab.Persistence.Default.Xml;
     39using RunCreationClient = HeuristicLab.Clients.OKB.RunCreation.RunCreationClient;
     40using SingleObjectiveOKBProblem = HeuristicLab.Clients.OKB.RunCreation.SingleObjectiveOKBProblem;
    3841
    3942namespace HeuristicLab.OptimizationExpertSystem {
     
    6871
    6972    [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; }
    7376      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 {
    8486      get { return problem; }
    8587      set {
     
    109111    }
    110112
     113    [Storable]
     114    private BidirectionalLookup<long, IRun> algorithmId2RunMapping;
     115    [Storable]
     116    private BidirectionalDictionary<long, IAlgorithm> algorithmId2AlgorithmInstanceMapping;
     117
    111118    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      }
    113122    }
    114123
     
    118127      : base(original, cloner) {
    119128      runs = cloner.Clone(original.runs);
    120       algorithmInstances = cloner.Clone(original.algorithmInstances);
    121       problem = cloner.Clone(original.problem);
     129      knowledgeBase = cloner.Clone(original.knowledgeBase);
    122130      suggestedInstances = cloner.Clone(original.suggestedInstances);
    123131      readOnlySuggestedInstances = suggestedInstances.AsReadOnly();
    124132      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      }
    125142      RegisterEventHandlers();
    126143    }
     
    129146      Description = ItemDescription;
    130147      runs = new RunCollection();
    131       algorithmInstances = new ItemList<IAlgorithm>();
     148      knowledgeBase = new RunCollection();
    132149      suggestedInstances = new ItemList<IAlgorithm>();
    133150      readOnlySuggestedInstances = suggestedInstances.AsReadOnly();
    134151      problemInstances = new RunCollection();
     152      problem = new SingleObjectiveOKBProblem();
     153      algorithmId2RunMapping = new BidirectionalLookup<long, IRun>();
     154      algorithmId2AlgorithmInstanceMapping = new BidirectionalDictionary<long, IAlgorithm>();
    135155      RegisterEventHandlers();
     156    }
     157
     158    private void ProblemOnProblemChanged(object sender, EventArgs eventArgs) {
     159      if (Problem == null) return;
    136160    }
    137161
     
    147171
    148172    private void RegisterEventHandlers() {
     173      problem.ProblemChanged += ProblemOnProblemChanged;
    149174      runs.CollectionReset += InformationChanged;
    150175      runs.ItemsAdded += InformationChanged;
     
    152177      runs.Reset += InformationChanged;
    153178      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;
    157182    }
    158183
     
    181206      alglib.pcabuildbasis(ds, instanceCounter, flaValues.Count, out info, out s2, out v);
    182207
    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()));
    188208      ProblemInstances.UpdateOfRunsInProgress = true;
    189209      try {
    190210        instanceCounter = 0;
    191211        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 
    196212          double x = 0, y = 0;
    197213          for (var feature = 0; feature < flaValues.Count; feature++) {
     
    208224
    209225          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;
    211351          var bkQuality = ((DoubleValue)instance.Parameters["BestKnownQuality"]).Value;
    212352          var maximization = ((BoolValue)instance.Parameters["Maximization"]).Value;
     
    219359              var result = ExpectedRuntimeHelper.CalculateErt(kvp.Value, "QualityPerEvaluations", bkQuality * target, maximization);
    220360              var resultName = algInstanceName + "@" + ((target - 1) * 100) + "%";
     361              IItem item;
    221362              if (instance.Results.TryGetValue(resultName, out item)) {
    222363                ((DoubleValue)item).Value = Math.Log10(result.ExpectedRuntime);
     
    225366          }
    226367        }
    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; }
    305370    }
    306371
     
    308373      if (Problem == null) return;
    309374      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)) {
    312376        var avgQuality = 0.0;
    313377        var counter = 0;
     
    320384        }
    321385        avgQuality /= counter;
    322         instances.Add(avgQuality, instance);
     386        instances.Add(avgQuality, relevantRuns.Key);
    323387      }
    324388
    325389      suggestedInstances.Clear();
    326       var instanceLadder = instances.Select(x => x.Value);
     390      var instanceLadder = instances.Select(x => (IAlgorithm)x.Value.Clone());
    327391      suggestedInstances.AddRange(Maximization ? instanceLadder.Reverse() : instanceLadder);
    328392    }
Note: See TracChangeset for help on using the changeset viewer.