Free cookie consent management tool by TermsFeed Policy Generator

Ignore:
Timestamp:
12/18/17 14:38:18 (7 years ago)
Author:
ddorfmei
Message:

#2747: Improved hard-coded genetic algorithm

  • implemented restart strategy
  • implemented 1-Opt algorithm
  • added parameters to control restart strategy and optimal assignment strategy
  • additional results: best solution found after number of generations, jobs/nests (for evaluation only)
File:
1 edited

Legend:

Unmodified
Added
Removed
  • branches/CFSAP/HeuristicLab.Problems.Scheduling.CFSAP/3.3/MultiNestCFSAPSolvingStrategy.cs

    r15472 r15533  
    1212
    1313namespace HeuristicLab.Problems.Scheduling.CFSAP {
    14   [Item("MultiNest CFSAP Solver", "Solving strategy that applies an algorithm instace to the worst nest.")]
     14  [Item("MultiNest CFSAP Solver", "Solving strategy that applies an algorithm instance to the worst nest.")]
    1515  [StorableClass]
    1616  [Creatable(CreatableAttribute.Categories.Algorithms)]
     
    3333    }
    3434
    35 
    3635    public IFixedValueParameter<StringValue> EvaluatedSolutionsNameParameter {
    3736      get { return (IFixedValueParameter<StringValue>)Parameters["EvaluatedSolutionsName"]; }
     37    }
     38
     39    public IValueParameter<BoolValue> RestartParameter {
     40      get { return (IValueParameter<BoolValue>)Parameters["Restart"]; }
     41    }
     42
     43    public IValueParameter<IntValue> MinTriesParameter {
     44      get { return (IValueParameter<IntValue>)Parameters["Restart.MinTries"]; }
     45    }
     46
     47    public IValueParameter<DoubleValue> LastSuccessPercentageParameter {
     48      get { return (IValueParameter<DoubleValue>)Parameters["Restart.LastSuccessPercentage"]; }
    3849    }
    3950
     
    5364    }
    5465
     66    public bool Restart {
     67      get => RestartParameter.Value.Value;
     68      set => RestartParameter.Value.Value = value;
     69    }
     70
     71    public int MinTries {
     72      get => MinTriesParameter.Value.Value;
     73      set => MinTriesParameter.Value.Value = value;
     74    }
     75
     76    public double LastSuccessPercentage {
     77      get => LastSuccessPercentageParameter.Value.Value;
     78      set => LastSuccessPercentageParameter.Value.Value = value;
     79    }
     80
    5581    [StorableConstructor]
    5682    protected MultiNestCFSAPSolvingStrategy(bool deserializing) : base(deserializing) { }
     83
    5784    protected MultiNestCFSAPSolvingStrategy(MultiNestCFSAPSolvingStrategy original, Cloner cloner)
    5885      : base(original, cloner) {
     
    6794      if (original.qualityPerEvaluations != null)
    6895        qualityPerEvaluations = cloner.Clone(original.qualityPerEvaluations);
    69     }
     96
     97      restart = original.restart;
     98      minTries = original.minTries;
     99      lastSuccessPercentage = original.lastSuccessPercentage;
     100    }
     101
    70102    public MultiNestCFSAPSolvingStrategy() {
    71103      Parameters.Add(new ValueParameter<IAlgorithm>("Solver", "The actual solver template.") { GetsCollected = false });
    72104      Parameters.Add(new FixedValueParameter<TimeSpanValue>("MaximumRuntime", "The maximum time that the strategy should run.", new TimeSpanValue(TimeSpan.FromSeconds(60))));
    73105      Parameters.Add(new FixedValueParameter<StringValue>("EvaluatedSolutionsName", "The name of the result that shows the number of evaluated solutions by the actual solver.", new StringValue("EvaluatedSolutions")));
    74     }
    75    
     106      Parameters.Add(new ValueParameter<BoolValue>("Restart", "Whether the worst algorithm should be restarted, if it doesn't find any better solutions.", new BoolValue(restart)));
     107      Parameters.Add(new ValueParameter<IntValue>("Restart.MinTries", "The minimum number of tries before the worst algorithm is restarted.", new IntValue(minTries)));
     108      Parameters.Add(new ValueParameter<DoubleValue>("Restart.LastSuccessPercentage", "Only if the last found best solution is older than x percent of the total number of tries, the worst algorithm is restarted.", new DoubleValue(lastSuccessPercentage)));
     109    }
     110
    76111    public override IDeepCloneable Clone(Cloner cloner) {
    77112      return new MultiNestCFSAPSolvingStrategy(this, cloner);
    78113    }
    79 
    80114
    81115    [StorableHook(HookType.AfterDeserialization)]
     
    83117      if (!Parameters.ContainsKey("EvaluatedSolutionsName"))
    84118        Parameters.Add(new FixedValueParameter<StringValue>("EvaluatedSolutionsName", "The name of the result that shows the number of evaluated solutions by the actual solver.", new StringValue("EvaluatedSolutions")));
     119      if (!Parameters.ContainsKey("Restart"))
     120        Parameters.Add(new ValueParameter<BoolValue>(nameof(Restart), "Whether the worst algorithm should be restarted, if it doesn't find any better solutions.", new BoolValue(restart)));
     121      if (!Parameters.ContainsKey("Restart.MinTries"))
     122        Parameters.Add(new ValueParameter<IntValue>("Restart.MinTries", "The minimum number of tries before the worst algorithm is restarted.", new IntValue(minTries)));
     123      if (!Parameters.ContainsKey("Restart.LastSuccessPercentage"))
     124        Parameters.Add(new ValueParameter<DoubleValue>("Restart.LastSuccessPercentage", "Only if the last found best solution is older than x percent of the total number of tries, the worst algorithm is restarted.", new DoubleValue(lastSuccessPercentage)));
    85125    }
    86126
     
    95135    [Storable]
    96136    private IndexedDataTable<double> qualityPerEvaluations;
     137    [Storable]
     138    private bool restart = true;
     139    [Storable]
     140    private int minTries = 10000;
     141    [Storable]
     142    private double lastSuccessPercentage = 0.1;
    97143
    98144    protected override void OnPrepared() {
     
    117163        cfsap.UpdateEncoding();
    118164        algorithms.Add(clone);
    119         algorithmsResults.Add(new Result("Nest " + (n + 1), clone.Results));
     165        algorithmsResults.Add(new Result($"Nest {n + 1}", clone.Results));
    120166        clone.Start();
    121167      }
     
    133179      qualityPerEvaluations.Rows.Add(qpeRow);
    134180      double evaluations = GetEvaluatedSolutions();
    135       qpeRow.Values.Add(Tuple.Create((double)evaluations, (double)min));
    136       qpeRow.Values.Add(Tuple.Create((double)evaluations, (double)min));
     181      qpeRow.Values.Add(Tuple.Create(evaluations, (double)min));
     182      qpeRow.Values.Add(Tuple.Create(evaluations, (double)min));
    137183
    138184      Results.Add(new Result("Nest with maximum T", new IntValue(worst.Index + 1)));
    139185      Results.Add(new Result("Maximum T", new IntValue(min)));
    140186      Results.Add(new Result("BestQuality", new DoubleValue(min)));
     187      Results.Add(new Result("Best Solution Found After Evaluated Solutions", new DoubleValue(evaluations)));
    141188      Results.Add(new Result("Best Solution Found At", new TimeSpanValue(ExecutionTime)));
    142189      Results.Add(new Result("Delta T", new PercentValue((min - Problem.BestKnownQuality) / Problem.BestKnownQuality)));
     
    144191      Results.Add(new Result("QualityPerClock", qualityPerClock));
    145192      Results.Add(new Result("QualityPerEvaluations", qualityPerEvaluations));
     193      Results.Add(new Result("Tries", new IntValue(nests)));
     194      Results.Add(new Result("Nests", new IntValue(nests)));
     195      Results.Add(new Result("Jobs", new IntValue(Problem.ProcessingTimes.First().Count() / Problem.SetupTimes.First().Count())));
    146196
    147197      base.Initialize(cancellationToken);
     
    149199
    150200    private double GetEvaluatedSolutions() {
    151       if (algorithmsResults == null) throw new InvalidOperationException("Strategy has not been started yet.");
     201      if (algorithmsResults == null)
     202        throw new InvalidOperationException("Strategy has not been started yet.");
    152203      return algorithmsResults.Select(x => {
    153         IResult res;
    154         if (((ResultCollection)x.Value).TryGetValue(EvaluatedSolutionsName, out res)) {
     204        if (((ResultCollection)x.Value).TryGetValue(EvaluatedSolutionsName, out var res)) {
    155205          var itm = res.Value;
    156           if (itm is IntValue) return ((IntValue)itm).Value;
    157           else if (itm is DoubleValue) return ((DoubleValue)itm).Value;
     206          if (itm is IntValue)
     207            return ((IntValue)itm).Value;
     208          else if (itm is DoubleValue)
     209            return ((DoubleValue)itm).Value;
    158210        }
    159         throw new InvalidOperationException("No result " + EvaluatedSolutionsName + " in the collection of " + x.Name);
     211        throw new InvalidOperationException($"No result {EvaluatedSolutionsName} in the collection of {x.Name}");
    160212      }).Sum();
    161213    }
    162214
    163215    protected override void Run(CancellationToken cancellationToken) {
     216      var evaluationsPrevTries = 0.0;
    164217      var worst = qualities.Select((v, i) => new { Index = i, Quality = v }).MaxItems(x => x.Quality).First();
    165218      var min = worst.Quality;
    166219
    167       while (ExecutionTime < MaximumRuntime) {
    168         algorithms[worst.Index].Start(cancellationToken);
    169         qualities[worst.Index] = (int)((DoubleValue)algorithms[worst.Index].Results["BestQuality"].Value).Value;
    170         worst = qualities.Select((v, i) => new { Index = i, Quality = v }).MaxItems(x => x.Quality).First();
    171 
    172         var evaluations = GetEvaluatedSolutions();
    173         var time = ExecutionTime.TotalSeconds;
    174         var qpcRow = qualityPerClock.Rows.First();
    175         var qpeRow = qualityPerEvaluations.Rows.First();
    176         qpcRow.Values[qpcRow.Values.Count - 1] = Tuple.Create(time, (double)min);
    177         qpeRow.Values[qpeRow.Values.Count - 1] = Tuple.Create(evaluations, (double)min);
    178 
    179         if (worst.Quality < min) {
    180           min = worst.Quality;
    181           ((IntValue)Results["Nest with maximum T"].Value).Value = worst.Index + 1;
    182           ((IntValue)Results["Maximum T"].Value).Value = min;
    183           ((DoubleValue)Results["BestQuality"].Value).Value = min;
    184           ((TimeSpanValue)Results["Best Solution Found At"].Value).Value = TimeSpan.FromSeconds(time);
    185           ((PercentValue)Results["Delta T"].Value).Value = (min - Problem.BestKnownQuality) / Problem.BestKnownQuality;
    186           qpcRow.Values.Add(Tuple.Create(time, (double)min));
    187           qpeRow.Values.Add(Tuple.Create(evaluations, (double)min));
     220      var overallBestQualities = algorithms.Select(a => ((DoubleValue)a.Results["BestQuality"].Value).Value).ToArray();
     221
     222      do {
     223        var tries = 0;
     224        var lastSuccess = 0;
     225
     226        while (ExecutionTime < MaximumRuntime && !cancellationToken.IsCancellationRequested &&
     227            (!Restart || (tries < MinTries || (tries - lastSuccess) < tries * LastSuccessPercentage))) {
     228          ++tries;
     229          ++((IntValue)Results["Tries"].Value).Value;
     230
     231          algorithms[worst.Index].Start(cancellationToken);
     232          qualities[worst.Index] = (int)((DoubleValue)algorithms[worst.Index].Results["BestQuality"].Value).Value;
     233          worst = qualities.Select((v, i) => new { Index = i, Quality = v }).MaxItems(x => x.Quality).First();
     234
     235          var evaluations = evaluationsPrevTries + GetEvaluatedSolutions();
     236          var time = ExecutionTime.TotalSeconds;
     237          var qpcRow = qualityPerClock.Rows.First();
     238          var qpeRow = qualityPerEvaluations.Rows.First();
     239          qpcRow.Values[qpcRow.Values.Count - 1] = Tuple.Create(time, (double)Math.Min(worst.Quality, min));
     240          qpeRow.Values[qpeRow.Values.Count - 1] = Tuple.Create(evaluations, (double)Math.Min(worst.Quality, min));
     241
     242          if (worst.Quality < min) {
     243            min = worst.Quality;
     244            overallBestQualities[worst.Index] = min;
     245            ((IntValue)Results["Nest with maximum T"].Value).Value = worst.Index + 1;
     246            ((IntValue)Results["Maximum T"].Value).Value = min;
     247            ((DoubleValue)Results["BestQuality"].Value).Value = min;
     248            ((DoubleValue)Results["Best Solution Found After Evaluated Solutions"].Value).Value = evaluations;
     249            ((TimeSpanValue)Results["Best Solution Found At"].Value).Value = TimeSpan.FromSeconds(time);
     250            ((PercentValue)Results["Delta T"].Value).Value = (min - Problem.BestKnownQuality) / Problem.BestKnownQuality;
     251            qpcRow.Values.Add(Tuple.Create(time, (double)min));
     252            qpeRow.Values.Add(Tuple.Create(evaluations, (double)min));
     253            lastSuccess = tries;
     254          }
    188255        }
    189256
    190         if (cancellationToken.IsCancellationRequested) return;
     257        if (cancellationToken.IsCancellationRequested || ExecutionTime >= MaximumRuntime || !Restart)
     258          break;
     259
     260        evaluationsPrevTries += GetEvaluatedSolutions();
     261
     262        // restart worst algorithm
     263        var worstAlgorithm = algorithms[worst.Index];
     264        var prevGenerations = ((IntValue)worstAlgorithm.Results["Generation"].Value).Value;
     265        var prevEvaluatedSolutions = ((IntValue)worstAlgorithm.Results["EvaluatedSolutions"].Value).Value;
     266
     267        worstAlgorithm.Prepare();
     268        worstAlgorithm.Start(cancellationToken);
     269        ++((IntValue)Results["Tries"].Value).Value;
     270
     271        ((IntValue)worstAlgorithm.Results["Generation"].Value).Value += prevGenerations;
     272        ((IntValue)worstAlgorithm.Results["EvaluatedSolutions"].Value).Value += prevEvaluatedSolutions;
     273      } while (Restart);
     274
     275      for (var i = 0; i < algorithms.Count(); ++i) {
     276        if (overallBestQualities[i] < ((DoubleValue)algorithms[i].Results["BestQuality"].Value).Value) {
     277          ((DoubleValue)algorithms[i].Results["BestQuality"].Value).Value = overallBestQualities[i];
     278        }
    191279      }
    192280    }
Note: See TracChangeset for help on using the changeset viewer.