#region License Information /* HeuristicLab * Copyright (C) 2002-2019 Heuristic and Evolutionary Algorithms Laboratory (HEAL) * * This file is part of HeuristicLab. * * HeuristicLab is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * HeuristicLab is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with HeuristicLab. If not, see . */ #endregion using HeuristicLab.Common; using HeuristicLab.Core; using HeuristicLab.Data; using HeuristicLab.Encodings.RealVectorEncoding; using HeuristicLab.Operators; using HeuristicLab.Parameters; using HEAL.Fossil; namespace HeuristicLab.Algorithms.GradientDescent { [StorableType("DC5D8418-FD1E-4D4C-AEF6-79F77AD8A5D9")] [Item(Name = "LBFGS MakeStep", Description = "Makes a step in the LM-BFGS optimization algorithm.")] public sealed class LbfgsMakeStep : SingleSuccessorOperator { private const string TerminationCriterionParameterName = "TerminationCriterion"; private const string PointParameterName = "Point"; private const string StateParameterName = "State"; #region Parameter Properties public ILookupParameter StateParameter { get { return (ILookupParameter)Parameters[StateParameterName]; } } public ILookupParameter TerminationCriterionParameter { get { return (ILookupParameter)Parameters[TerminationCriterionParameterName]; } } public ILookupParameter PointParameter { get { return (ILookupParameter)Parameters[PointParameterName]; } } #endregion #region Properties private LbfgsState State { get { return StateParameter.ActualValue; } } #endregion [StorableConstructor] private LbfgsMakeStep(StorableConstructorFlag _) : base(_) { } private LbfgsMakeStep(LbfgsMakeStep original, Cloner cloner) : base(original, cloner) { } public LbfgsMakeStep() : base() { // in & out Parameters.Add(new LookupParameter(StateParameterName, "The state of the LM-BFGS algorithm.")); // out Parameters.Add(new LookupParameter(TerminationCriterionParameterName, "The termination criterion indicating that the LM-BFGS optimization algorithm should stop.")); Parameters.Add(new LookupParameter(PointParameterName, "The next point that should be evaluated in the LM-BFGS algorithm.")); } public override IDeepCloneable Clone(Cloner cloner) { return new LbfgsMakeStep(this, cloner); } public override IOperation Apply() { var state = State; bool @continue = alglib.minlbfgs.minlbfgsiteration(state.State); TerminationCriterionParameter.ActualValue = new BoolValue(!@continue); if (@continue) { PointParameter.ActualValue = new RealVector(state.State.x); } else { double[] x = new double[state.State.x.Length]; alglib.minlbfgs.minlbfgsreport rep = new alglib.minlbfgs.minlbfgsreport(); alglib.minlbfgs.minlbfgsresults(state.State, ref x, rep); if (rep.terminationtype < 0) { if (rep.terminationtype == -1) throw new OperatorExecutionException(this, "Incorrect parameters were specified."); else if (rep.terminationtype == -2) throw new OperatorExecutionException(this, "Rounding errors prevent further improvement."); else if (rep.terminationtype == -7) throw new OperatorExecutionException(this, "Gradient verification failed."); } PointParameter.ActualValue = new RealVector(x); } return base.Apply(); } } }