heal-research / HeuristicLab

HeuristicLab - An environment for heuristic and evolutionary optimization
https://dev.heuristiclab.com
GNU General Public License v3.0
39 stars 16 forks source link

When using multi encoding in combination with several symbolic expression trees, only the grammar of the first used symbolic expression tree is used to generate syntax trees. #2997

Open HeuristicLab-Trac-Bot opened 5 years ago

HeuristicLab-Trac-Bot commented 5 years ago

Issue migrated from trac ticket # 2997

milestone: HeuristicLab 3.3.17 | component: Encodings.SymbolicExpressionTreeEncoding | priority: medium

2019-03-19 12:30:54: rhanghof created the issue


When using multi encoding in combination with several symbolic expression trees, only the grammar of the first used symbolic expression tree is used to generate syntax trees. The grammar for creating the syntax trees is stored in the Global Scope and cloned from the grammar of the first syntax tree in the encoding when first used. The setting of the cloned grammar in the global scope can be found in the method InstrumentedApply of the class SymbolicExpressionTreeCreator. [[BR]] Due to the query if (ClonedSymbolicExpressionTreeGrammarParameter.ActualValue == null) it is only set the very first time. Thus it is not possible to set the grammar for another symbolic expression tree.

HeuristicLab-Trac-Bot commented 5 years ago

2019-03-19 12:48:11: rhanghof changed component from Problems.DataAnalysis.Symbolic to Encodings.SymbolicExpressionTreeEncoding

HeuristicLab-Trac-Bot commented 5 years ago

2019-03-19 12:48:11: rhanghof edited the issue description

HeuristicLab-Trac-Bot commented 5 years ago

2019-03-19 16:55:29: @mkommend commented


Please attach a minimal sample (multi-encoding with two symbolic expression tree encodings and vastly different grammars) that reproduces the issue for debugging purposes.

HeuristicLab-Trac-Bot commented 5 years ago

2019-03-19 16:55:29: @mkommend

HeuristicLab-Trac-Bot commented 5 years ago

2019-03-25 10:06:40: rhanghof uploaded file Genetic Algorithm (GA) - Syntax Expression Tree MultiEncoding sample.hl (153.7 KiB)

Syntax expression tree multi-encoding sample

HeuristicLab-Trac-Bot commented 5 years ago

2019-04-04 12:38:38: @mkommend commented


Unfortunately the provided example cannot be loaded with a standard version of HL, because it uses a proprietary plugin HeuristicLab.Problems.Matlab.ModelLearning or HeuristicLab.Problems.Matlab.ModelLearning.Optimization and maybe even others.

HeuristicLab-Trac-Bot commented 5 years ago

2019-04-04 16:47:48: @mkommend changed status from new to assigned

HeuristicLab-Trac-Bot commented 5 years ago

2019-04-04 16:47:48: @mkommend set owner to rhanghof

HeuristicLab-Trac-Bot commented 5 years ago

2019-04-08 12:51:38: rhanghof uploaded file Genetic Algorithm (GA) - Syntax Expression Tree MultiEncoding sample - update.hl (104.7 KiB)

Syntax expression tree multi-encoding sample

HeuristicLab-Trac-Bot commented 5 years ago

2019-06-26 12:13:00: @gkronber commented


Here is another small example where I have just spotted the same bug. Trees for t2 also contain terminals x,y,z instead of a,b,c.

#!csharp
namespace HeuristicLab.Problems.Programmable {
  public class CompiledSingleObjectiveProblemDefinition : CompiledProblemDefinition, ISingleObjectiveProblemDefinition {
    public bool Maximization { get { return false; } }

    public override void Initialize() {
      var g1 = new SimpleSymbolicExpressionGrammar();
      var g2 = new SimpleSymbolicExpressionGrammar();
      g1.AddSymbols(new string[] {"max", "add"}, 2, 2);
      g1.AddTerminalSymbols(new string[] {"x", "y", "z"});
      g2.AddSymbols(new string[] {"max", "add"}, 2, 2);
      g2.AddTerminalSymbols(new string[] {"a", "b", "c"});

      Encoding = new MultiEncoding()
        .Add(new SymbolicExpressionTreeEncoding("t1", g1, 50, 12))
        .Add(new SymbolicExpressionTreeEncoding("t2", g2, 50, 12))
      ;
    }

    public double Evaluate(Individual individual, IRandom random) {
      var trees # individual.Values.Select(v> v.Value).OfType<ISymbolicExpressionTree>().ToArray();

      var numAs = 0;
      var numXs = 0;
      foreach(var n in trees[0].Root.IterateNodesPrefix()) {
        if(n.Symbol.Name == "x") numXs++;
        else if(n.Symbol.Name == "a") numAs++;
      }
      foreach(var n in trees[1].Root.IterateNodesPrefix()) {
        if(n.Symbol.Name == "x") numXs++;
        else if(n.Symbol.Name == "a") numAs++;
      }

      return numAs + numXs;
    }

    public void Analyze(Individual[] individuals, double[] qualities, ResultCollection results, IRandom random) { }

    public IEnumerable<Individual> GetNeighbors(Individual individual, IRandom random) {  return Enumerable.Empty<Individual>();  }
  }
}
HeuristicLab-Trac-Bot commented 5 years ago

2019-07-23 21:27:08: @gkronber changed milestone from HeuristicLab 3.3.16 to HeuristicLab 3.3.17

HeuristicLab-Trac-Bot commented 3 years ago

2021-10-06 09:35:05: @mkommend changed status from assigned to accepted

HeuristicLab-Trac-Bot commented 3 years ago

2021-10-06 09:35:05: @mkommend changed owner from rhanghof to @mkommend

HeuristicLab-Trac-Bot commented 3 years ago

2021-10-06 09:45:31: @mkommend commented


I have investigated this issue as it is a blocker for the correct development of #3136.

The reason for this faulty behavior is that during the first execution of any tree creator the used grammar is cloned and put in the global scope. From now on only this cloned grammar is used for tree creation. In the case of a multi-encoding the cloning is performed only once and the tree creators for the other encoding parts detect the cloned grammar and wrongly use the cloned grammar, which could be vastly different from the configured one.

The reason for this strange behavior is AFAIK to avoid grammar manipulations when the algorithm is paused. Currently the grammar is set to readonly before it is cloned, thus preventing any manipulation. The readonly flag is afterwards removed in the ClearState method of the grammar, which is an IStatefulItem.

HeuristicLab-Trac-Bot commented 3 years ago

2021-10-06 09:47:33: @mkommend commented


IMHO the best solution is to remove this awkward and unusual cloning of grammars all together and work directly with the configured grammar object. Hence, we could also remove the IStatefulItem interface from grammars, which further simplifies the tree creation.

Additionally, the current behavior that tree creators use a cloned grammar is not consistent, because all other operators that require a grammar use the normal grammar or the one within the tree.

The only thing that does not work after the proposed changed is that grammar manipulations during algorithm execution (while it is in a paused state) is possible. However, this is a larger issue which affects all parameters of an algorithm / problem and should be tackled more generally. E.g. the GA's population size / manipulation rate / ... can all be modified during algorithm execution.

HeuristicLab-Trac-Bot commented 3 years ago

2021-10-06 09:47:33: @mkommend

HeuristicLab-Trac-Bot commented 3 years ago

2021-10-06 16:14:08: @mkommend commented


r18064: Simplified tree creator interface and removed cloning of grammars,