Free cookie consent management tool by TermsFeed Policy Generator

source: stable/HeuristicLab.Algorithms.GradientDescent/3.3/Lbfgs.cs @ 12128

Last change on this file since 12128 was 12009, checked in by ascheibe, 10 years ago

#2212 updated copyright year

File size: 11.6 KB
RevLine 
[8396]1
2#region License Information
3/* HeuristicLab
[12009]4 * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
[8396]5 *
6 * This file is part of HeuristicLab.
7 *
8 * HeuristicLab is free software: you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation, either version 3 of the License, or
11 * (at your option) any later version.
12 *
13 * HeuristicLab is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
20 */
21#endregion
22
23using System;
[9439]24using System.Linq;
25using HeuristicLab.Analysis;
[8396]26using HeuristicLab.Common;
27using HeuristicLab.Core;
28using HeuristicLab.Data;
[9127]29using HeuristicLab.Encodings.RealVectorEncoding;
[8396]30using HeuristicLab.Operators;
31using HeuristicLab.Optimization;
32using HeuristicLab.Parameters;
33using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
34using HeuristicLab.Random;
35
[8401]36namespace HeuristicLab.Algorithms.GradientDescent {
[8396]37  /// <summary>
38  /// Limited-Memory BFGS optimization algorithm.
39  /// </summary>
40  [Item("LM-BFGS", "The limited-memory BFGS (Broyden–Fletcher–Goldfarb–Shanno) optimization algorithm.")]
41  [Creatable("Algorithms")]
42  [StorableClass]
43  public sealed class LbfgsAlgorithm : HeuristicOptimizationEngineAlgorithm, IStorableContent {
44    public override Type ProblemType {
[9127]45      get { return typeof(ISingleObjectiveHeuristicOptimizationProblem); }
[8396]46    }
47
[9127]48    public new ISingleObjectiveHeuristicOptimizationProblem Problem {
49      get { return (ISingleObjectiveHeuristicOptimizationProblem)base.Problem; }
[8396]50      set { base.Problem = value; }
51    }
52
53    public string Filename { get; set; }
54
[9439]55    private const string AnalyzerParameterName = "Analyzer";
[8396]56    private const string MaxIterationsParameterName = "MaxIterations";
57    private const string ApproximateGradientsParameterName = "ApproximateGradients";
[8397]58    private const string SeedParameterName = "Seed";
59    private const string SetSeedRandomlyParameterName = "SetSeedRandomly";
[9409]60    private const string GradientCheckStepSizeParameterName = "GradientCheckStepSize";
[8396]61
62    #region parameter properties
[9439]63    public IValueParameter<IMultiAnalyzer> AnalyzerParameter {
64      get { return (IValueParameter<IMultiAnalyzer>)Parameters[AnalyzerParameterName]; }
65    }
[8396]66    public IValueParameter<IntValue> MaxIterationsParameter {
67      get { return (IValueParameter<IntValue>)Parameters[MaxIterationsParameterName]; }
68    }
[8397]69    public IValueParameter<IntValue> SeedParameter {
70      get { return (IValueParameter<IntValue>)Parameters[SeedParameterName]; }
71    }
72    public IValueParameter<BoolValue> SetSeedRandomlyParameter {
73      get { return (IValueParameter<BoolValue>)Parameters[SetSeedRandomlyParameterName]; }
74    }
[9409]75    public IValueParameter<DoubleValue> GradientStepSizeParameter {
76      get { return (IValueParameter<DoubleValue>)Parameters[GradientCheckStepSizeParameterName]; }
77    }
[8396]78    #endregion
79    #region properties
[9439]80    public IMultiAnalyzer Analyzer {
81      get { return AnalyzerParameter.Value; }
82      set { AnalyzerParameter.Value = value; }
83    }
[8396]84    public int MaxIterations {
85      set { MaxIterationsParameter.Value.Value = value; }
86      get { return MaxIterationsParameter.Value.Value; }
87    }
[8397]88    public int Seed { get { return SeedParameter.Value.Value; } set { SeedParameter.Value.Value = value; } }
89    public bool SetSeedRandomly { get { return SetSeedRandomlyParameter.Value.Value; } set { SetSeedRandomlyParameter.Value.Value = value; } }
[8396]90    #endregion
[8397]91
[9127]92    [Storable]
93    private LbfgsInitializer initializer;
94    [Storable]
95    private LbfgsMakeStep makeStep;
96    [Storable]
97    private LbfgsUpdateResults updateResults;
98    [Storable]
99    private LbfgsAnalyzer analyzer;
100    [Storable]
101    private Placeholder solutionCreator;
102    [Storable]
103    private Placeholder evaluator;
104
[8396]105    [StorableConstructor]
106    private LbfgsAlgorithm(bool deserializing) : base(deserializing) { }
107    private LbfgsAlgorithm(LbfgsAlgorithm original, Cloner cloner)
108      : base(original, cloner) {
[9127]109      initializer = cloner.Clone(original.initializer);
110      makeStep = cloner.Clone(original.makeStep);
111      updateResults = cloner.Clone(original.updateResults);
112      analyzer = cloner.Clone(original.analyzer);
113      solutionCreator = cloner.Clone(original.solutionCreator);
114      evaluator = cloner.Clone(original.evaluator);
115      RegisterEvents();
[8396]116    }
117    public LbfgsAlgorithm()
118      : base() {
[9439]119      Parameters.Add(new ValueParameter<IMultiAnalyzer>(AnalyzerParameterName, "The analyzers that will be executed on the solution.", new MultiAnalyzer()));
[8396]120      Parameters.Add(new ValueParameter<IntValue>(MaxIterationsParameterName, "The maximal number of iterations for.", new IntValue(20)));
[8397]121      Parameters.Add(new ValueParameter<IntValue>(SeedParameterName, "The random seed used to initialize the new pseudo random number generator.", new IntValue(0)));
122      Parameters.Add(new ValueParameter<BoolValue>(SetSeedRandomlyParameterName, "True if the random seed should be set to a random value, otherwise false.", new BoolValue(true)));
[8396]123      Parameters.Add(new ValueParameter<BoolValue>(ApproximateGradientsParameterName, "Indicates that gradients should be approximated.", new BoolValue(true)));
[9409]124      Parameters.Add(new OptionalValueParameter<DoubleValue>(GradientCheckStepSizeParameterName, "Step size for the gradient check (should be used for debugging the gradient calculation only)."));
125      // these parameter should not be changed usually
126      Parameters[ApproximateGradientsParameterName].Hidden = true;
127      Parameters[GradientCheckStepSizeParameterName].Hidden = true;
[8396]128
129      var randomCreator = new RandomCreator();
[9127]130      solutionCreator = new Placeholder();
131      initializer = new LbfgsInitializer();
132      makeStep = new LbfgsMakeStep();
[8396]133      var branch = new ConditionalBranch();
[9127]134      evaluator = new Placeholder();
135      updateResults = new LbfgsUpdateResults();
[9439]136      var analyzerPlaceholder = new Placeholder();
137      var finalAnalyzerPlaceholder = new Placeholder();
[8396]138
139      OperatorGraph.InitialOperator = randomCreator;
140
[8397]141      randomCreator.SeedParameter.ActualName = SeedParameterName;
142      randomCreator.SeedParameter.Value = null;
143      randomCreator.SetSeedRandomlyParameter.ActualName = SetSeedRandomlyParameterName;
144      randomCreator.SetSeedRandomlyParameter.Value = null;
[8396]145      randomCreator.Successor = solutionCreator;
146
[9409]147      solutionCreator.Name = "(Solution Creator)";
[9127]148      solutionCreator.Successor = initializer;
[8396]149
[9127]150      initializer.IterationsParameter.ActualName = MaxIterationsParameterName;
151      initializer.ApproximateGradientsParameter.ActualName = ApproximateGradientsParameterName;
152      initializer.Successor = makeStep;
[8396]153
[9127]154      makeStep.StateParameter.ActualName = initializer.StateParameter.Name;
[8396]155      makeStep.Successor = branch;
156
157      branch.ConditionParameter.ActualName = makeStep.TerminationCriterionParameter.Name;
158      branch.FalseBranch = evaluator;
[9439]159      branch.TrueBranch = finalAnalyzerPlaceholder;
[8396]160
[9409]161      evaluator.Name = "(Evaluator)";
[8396]162      evaluator.Successor = updateResults;
163
[9127]164      updateResults.StateParameter.ActualName = initializer.StateParameter.Name;
[8396]165      updateResults.ApproximateGradientsParameter.ActualName = ApproximateGradientsParameterName;
[9439]166      updateResults.Successor = analyzerPlaceholder;
[8396]167
[9439]168      analyzerPlaceholder.Name = "(Analyzer)";
169      analyzerPlaceholder.OperatorParameter.ActualName = AnalyzerParameterName;
170      analyzerPlaceholder.Successor = makeStep;
171
172      finalAnalyzerPlaceholder.Name = "(Analyzer)";
173      finalAnalyzerPlaceholder.OperatorParameter.ActualName = AnalyzerParameterName;
174      finalAnalyzerPlaceholder.Successor = null;
175
176      analyzer = new LbfgsAnalyzer();
[9127]177      analyzer.StateParameter.ActualName = initializer.StateParameter.Name;
[8396]178    }
179
180    [StorableHook(HookType.AfterDeserialization)]
[9127]181    private void AfterDeserialization() {
182      RegisterEvents();
183    }
[8396]184
185    public override IDeepCloneable Clone(Cloner cloner) {
186      return new LbfgsAlgorithm(this, cloner);
187    }
[9127]188
189    #region events
190    private void RegisterEvents() {
191      if (Problem != null) {
192        RegisterSolutionCreatorEvents();
193        RegisterEvaluatorEvents();
194      }
195    }
196
197    protected override void OnProblemChanged() {
198      base.OnProblemChanged();
199      if (Problem != null) {
200        RegisterEvents();
201        solutionCreator.OperatorParameter.ActualName = Problem.SolutionCreatorParameter.Name;
202        evaluator.OperatorParameter.ActualName = Problem.EvaluatorParameter.Name;
[9439]203        UpdateAnalyzers();
204        ParameterizeOperators();
[9127]205      }
206    }
207
208    protected override void Problem_SolutionCreatorChanged(object sender, EventArgs e) {
209      base.Problem_SolutionCreatorChanged(sender, e);
210      RegisterSolutionCreatorEvents();
211      ParameterizeOperators();
212    }
213
214    protected override void Problem_EvaluatorChanged(object sender, EventArgs e) {
215      base.Problem_EvaluatorChanged(sender, e);
216      RegisterEvaluatorEvents();
217      ParameterizeOperators();
218    }
219
[9439]220    protected override void Problem_OperatorsChanged(object sender, EventArgs e) {
221      base.Problem_OperatorsChanged(sender, e);
222      UpdateAnalyzers();
223    }
224
[9127]225    private void RegisterSolutionCreatorEvents() {
[9408]226      var realVectorCreator = Problem.SolutionCreator as IRealVectorCreator;
[9127]227      // ignore if we have a different kind of problem
228      if (realVectorCreator != null) {
229        realVectorCreator.RealVectorParameter.ActualNameChanged += (sender, args) => ParameterizeOperators();
230      }
231    }
232
233    private void RegisterEvaluatorEvents() {
234      Problem.Evaluator.QualityParameter.ActualNameChanged += (sender, args) => ParameterizeOperators();
235    }
236    #endregion
237
238    protected override void OnStarted() {
[9408]239      var realVectorCreator = Problem.SolutionCreator as IRealVectorCreator;
[9127]240      // must catch the case that user loaded an unsupported problem
241      if (realVectorCreator == null)
242        throw new InvalidOperationException("LM-BFGS only works with problems using a real-value encoding.");
243      base.OnStarted();
244    }
245
246    public override void Prepare() {
247      if (Problem != null) base.Prepare();
248    }
249
[9439]250    private void UpdateAnalyzers() {
251      Analyzer.Operators.Clear();
252      if (Problem != null) {
253        foreach (var a in Problem.Operators.OfType<IAnalyzer>()) {
254          foreach (var param in a.Parameters.OfType<IScopeTreeLookupParameter>())
255            param.Depth = 0;
256          Analyzer.Operators.Add(a, a.EnabledByDefault);
257        }
258      }
259      Analyzer.Operators.Add(analyzer, analyzer.EnabledByDefault);
260    }
261
[9127]262    private void ParameterizeOperators() {
[9408]263      var realVectorCreator = Problem.SolutionCreator as IRealVectorCreator;
[9127]264      // ignore if we have a different kind of problem
265      if (realVectorCreator != null) {
266        var realVectorParameterName = realVectorCreator.RealVectorParameter.ActualName;
267        initializer.PointParameter.ActualName = realVectorParameterName;
268        makeStep.PointParameter.ActualName = realVectorParameterName;
269        analyzer.PointParameter.ActualName = realVectorParameterName;
270      }
271
272      var qualityParameterName = Problem.Evaluator.QualityParameter.ActualName;
273      updateResults.QualityParameter.ActualName = qualityParameterName;
274      analyzer.QualityParameter.ActualName = qualityParameterName;
275    }
[8396]276  }
277}
Note: See TracBrowser for help on using the repository browser.