Changeset 18184


Ignore:
Timestamp:
01/12/22 14:09:02 (9 days ago)
Author:
mkommend
Message:

#3136: Refactored structured GP problem.

Location:
branches/3136_Structural_GP
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • branches/3136_Structural_GP/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/SingleObjective/StructuredSymbolicRegressionSingleObjectiveProblem.cs

    r18182 r18184  
    11using System;
    2 using System.Collections.Generic;
    32using System.Linq;
    43using HEAL.Attic;
    54using HeuristicLab.Common;
    65using HeuristicLab.Core;
    7 using HeuristicLab.Data;
    86using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
    97using HeuristicLab.Optimization;
     
    2826
    2927    private const string SymbolicExpressionTreeName = "SymbolicExpressionTree";
    30     private const string VariableName = "Variable";
    3128
    3229    private const string StructureTemplateDescriptionText =
     
    127124    }
    128125
    129     public StructuredSymbolicRegressionSingleObjectiveProblem(StructuredSymbolicRegressionSingleObjectiveProblem original,
    130       Cloner cloner) : base(original, cloner) {
     126    public StructuredSymbolicRegressionSingleObjectiveProblem(StructuredSymbolicRegressionSingleObjectiveProblem original, Cloner cloner) : base(original, cloner) {
    131127      RegisterEventHandlers();
    132128    }
     129
     130    public override IDeepCloneable Clone(Cloner cloner) =>
     131      new StructuredSymbolicRegressionSingleObjectiveProblem(this, cloner);
    133132
    134133    [StorableConstructor]
     
    143142    #endregion
    144143
    145     #region Cloning
    146     public override IDeepCloneable Clone(Cloner cloner) =>
    147       new StructuredSymbolicRegressionSingleObjectiveProblem(this, cloner);
    148     #endregion
     144    private void RegisterEventHandlers() {
     145      if (StructureTemplate != null) {
     146        StructureTemplate.Changed += OnTemplateChanged;
     147      }
     148
     149      ProblemDataParameter.ValueChanged += ProblemDataParameterValueChanged;
     150    }
    149151
    150152    private void ProblemDataParameterValueChanged(object sender, EventArgs e) {
     
    153155    }
    154156
    155     private void RegisterEventHandlers() {
    156       if (StructureTemplate != null) {
    157         StructureTemplate.Changed += OnTemplateChanged;
    158       }
    159 
    160       ProblemDataParameter.ValueChanged += ProblemDataParameterValueChanged;
    161     }
    162 
    163157    private void OnTemplateChanged(object sender, EventArgs args) {
    164       SetupStructureTemplate();
    165     }
    166 
    167     private void SetupStructureTemplate() {
     158      SetupEncoding();
     159    }
     160
     161    private void SetupEncoding() {
    168162      foreach (var e in Encoding.Encodings.ToArray())
    169163        Encoding.Remove(e);
    170164
    171       foreach (var f in StructureTemplate.SubFunctions) {
    172         SetupVariables(f);
     165      foreach (var subFunction in StructureTemplate.SubFunctions) {
     166        subFunction.SetupVariables(ProblemData.AllowedInputVariables);
    173167        // to prevent the same encoding twice
    174         if (!Encoding.Encodings.Any(x => x.Name == f.Name))
    175           Encoding.Add(CreateEncoding(f));
    176       }
    177 
    178       ParameterizeEncoding();
     168        if (Encoding.Encodings.Any(x => x.Name == subFunction.Name)) continue; // duplicate subfunction
     169
     170        var encoding = new SymbolicExpressionTreeEncoding(
     171          subFunction.Name,
     172          subFunction.Grammar,
     173          subFunction.MaximumSymbolicExpressionTreeLength,
     174          subFunction.MaximumSymbolicExpressionTreeDepth);
     175        Encoding.Add(encoding);
     176      }
     177
     178      //set multi manipulator as default manipulator for all encoding parts
     179      var manipulator = (IParameterizedItem)Encoding.Operators.OfType<MultiEncodingManipulator>().FirstOrDefault();
     180      if (manipulator != null) {
     181        foreach (var param in manipulator.Parameters.OfType<ConstrainedValueParameter<IManipulator>>()) {
     182          var m = param.ValidValues.OfType<MultiSymbolicExpressionTreeManipulator>().FirstOrDefault();
     183          param.Value = m == null ? param.ValidValues.First() : m;
     184        }
     185      }
    179186    }
    180187
     
    198205
    199206    public override double Evaluate(Individual individual, IRandom random) {
    200       var tree = BuildTree(individual);
     207      var templateTree = StructureTemplate.Tree;
     208      if (templateTree == null)
     209        throw new ArgumentException("No structure template defined!");
     210
     211      var tree = BuildTree(templateTree, individual);
    201212
    202213      // NMSEConstraintsEvaluator sets linear scaling terms itself
     
    233244    }
    234245
    235     private ISymbolicExpressionTree BuildTree(Individual individual) {
    236       if (StructureTemplate.Tree == null)
    237         throw new ArgumentException("No structure template defined!");
    238 
    239       var templateTree = (ISymbolicExpressionTree)StructureTemplate.Tree.Clone();
     246    private static ISymbolicExpressionTree BuildTree(ISymbolicExpressionTree template, Individual individual) {
     247      var resolvedTree = (ISymbolicExpressionTree)template.Clone();
    240248
    241249      // build main tree
    242       foreach (var subFunctionTreeNode in templateTree.IterateNodesPrefix().OfType<SubFunctionTreeNode>()) {
     250      foreach (var subFunctionTreeNode in resolvedTree.IterateNodesPrefix().OfType<SubFunctionTreeNode>()) {
    243251        var subFunctionTree = individual.SymbolicExpressionTree(subFunctionTreeNode.Name);
    244252
    245         // add new tree
    246         var subTree = subFunctionTree.Root.GetSubtree(0)  // Start
    247                                           .GetSubtree(0); // Offset
     253        // extract function tree
     254        var subTree = subFunctionTree.Root.GetSubtree(0)  // StartSymbol
     255                                          .GetSubtree(0); // First Symbol
    248256        subTree = (ISymbolicExpressionTreeNode)subTree.Clone();
    249257        subFunctionTreeNode.AddSubtree(subTree);
    250 
    251       }
    252       return templateTree;
    253     }
    254 
    255     private SymbolicExpressionTreeEncoding CreateEncoding(SubFunction subFunction) {
    256       var encoding = new SymbolicExpressionTreeEncoding(
    257             subFunction.Name,
    258             subFunction.Grammar,
    259             subFunction.MaximumSymbolicExpressionTreeLength,
    260             subFunction.MaximumSymbolicExpressionTreeDepth);
    261       return encoding;
    262     }
    263 
    264     private void ParameterizeEncoding() {
    265       var manipulator = (IParameterizedItem)Encoding.Operators.OfType<MultiEncodingManipulator>().FirstOrDefault();
    266       if (manipulator != null) {
    267         foreach (var param in manipulator.Parameters.OfType<ConstrainedValueParameter<IManipulator>>()) {
    268           var m = param.ValidValues.OfType<MultiSymbolicExpressionTreeManipulator>().FirstOrDefault();
    269           param.Value = m == null ? param.ValidValues.First() : m;
    270         }
    271       }
    272     }
    273     private void SetupVariables(SubFunction subFunction) {
    274       var varSym = (Variable)subFunction.Grammar.GetSymbol(VariableName);
    275       if (varSym == null) {
    276         varSym = new Variable();
    277         subFunction.Grammar.AddSymbol(varSym);
    278       }
    279 
    280       var allVariables = ProblemData.InputVariables.Select(x => x.Value);
    281       var allInputs = allVariables.Where(x => x != ProblemData.TargetVariable);
    282 
    283       // set all variables
    284       varSym.AllVariableNames = allVariables;
    285 
    286       // set all allowed variables
    287       if (subFunction.Arguments.Contains("_")) {
    288         varSym.VariableNames = allInputs;
    289       } else {
    290         var vars = new List<string>();
    291         var exceptions = new List<Exception>();
    292         foreach (var arg in subFunction.Arguments) {
    293           if (allInputs.Contains(arg))
    294             vars.Add(arg);
    295           else
    296             exceptions.Add(new ArgumentException($"The argument '{arg}' for sub-function '{subFunction.Name}' is not a valid variable."));
    297         }
    298         if (exceptions.Any())
    299           throw new AggregateException(exceptions);
    300         varSym.VariableNames = vars;
    301       }
    302 
    303       varSym.Enabled = true;
    304     }
     258      }
     259      return resolvedTree;
     260    }
     261
    305262
    306263    public void Load(IRegressionProblemData data) {
  • branches/3136_Structural_GP/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/StructureTemplate/SubFunction.cs

    r18182 r18184  
    22using System.Collections.Generic;
    33using System.Linq;
    4 using System.Text;
    5 using System.Threading.Tasks;
    6 using HeuristicLab.Core;
    74using HEAL.Attic;
    85using HeuristicLab.Common;
    9 using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
     6using HeuristicLab.Core;
     7using HeuristicLab.Data;
    108using HeuristicLab.Parameters;
    11 using HeuristicLab.Data;
    129
    1310namespace HeuristicLab.Problems.DataAnalysis.Symbolic {
     
    6562    [StorableConstructor]
    6663    protected SubFunction(StorableConstructorFlag _) : base(_) { }
     64    public override IDeepCloneable Clone(Cloner cloner) =>
     65      new SubFunction(this, cloner);
    6766
    6867
     
    7372    #endregion
    7473
    75     #region Cloning
    76     public override IDeepCloneable Clone(Cloner cloner) =>
    77       new SubFunction(this, cloner);
    78     #endregion
    7974
    8075    #region Event Handling
     
    9590
    9691    public override bool Equals(object obj) => (obj is SubFunction other) && other.ToString() == ToString();
     92
     93    public void SetupVariables(IEnumerable<string> inputVariables) {
     94      var allowedInputVariables = new List<string>(inputVariables);
     95
     96      foreach (var varSym in Grammar.Symbols.OfType<Variable>()) {
     97        // set all variables
     98        varSym.AllVariableNames = allowedInputVariables;
     99
     100        // set all allowed variables
     101        if (Arguments.Contains("_")) {
     102          varSym.VariableNames = allowedInputVariables;
     103        } else {
     104          var vars = new List<string>();
     105          var exceptions = new List<Exception>();
     106          foreach (var arg in Arguments) {
     107            if (allowedInputVariables.Contains(arg))
     108              vars.Add(arg);
     109            else
     110              exceptions.Add(new ArgumentException($"The argument '{arg}' for sub-function '{Name}' is not a valid variable."));
     111          }
     112          if (exceptions.Any())
     113            throw new AggregateException(exceptions);
     114          varSym.VariableNames = vars;
     115        }
     116
     117        varSym.Enabled = true;
     118      }
     119    }
    97120  }
    98121}
Note: See TracChangeset for help on using the changeset viewer.