[11846] | 1 | using System;
|
---|
| 2 | using System.Collections.Generic;
|
---|
| 3 | using System.Diagnostics;
|
---|
| 4 | using System.Linq;
|
---|
| 5 | using System.Text;
|
---|
| 6 | using System.Text.RegularExpressions;
|
---|
| 7 | using HeuristicLab.Common;
|
---|
| 8 | using HeuristicLab.Core;
|
---|
| 9 | using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
|
---|
| 10 | using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
|
---|
| 11 | using HeuristicLab.PluginInfrastructure;
|
---|
| 12 |
|
---|
| 13 | namespace HeuristicLab.Problems.GrammaticalOptimization {
|
---|
| 14 | [NonDiscoverableType]
|
---|
| 15 | [StorableClass]
|
---|
| 16 | [Item("GenericSymbExprGrammar", "Represents a general grammar for grammatical optimization problems.")]
|
---|
| 17 | public class GenericSymbExprGrammar : SymbolicExpressionGrammar {
|
---|
| 18 | [StorableClass]
|
---|
| 19 | [Item("GenericSymbol", "")]
|
---|
| 20 | public sealed class GenericSymbol : Symbol {
|
---|
| 21 | private readonly int minimumArity = 1;
|
---|
| 22 | private readonly int maximumArity = byte.MaxValue;
|
---|
| 23 |
|
---|
| 24 | public override int MinimumArity { get { return minimumArity; } }
|
---|
| 25 | public override int MaximumArity { get { return maximumArity; } }
|
---|
| 26 |
|
---|
| 27 | [StorableConstructor]
|
---|
| 28 | private GenericSymbol(bool deserializing) : base(deserializing) { }
|
---|
| 29 | private GenericSymbol(GenericSymbol original, Cloner cloner) : base(original, cloner) { }
|
---|
| 30 | public override IDeepCloneable Clone(Cloner cloner) {
|
---|
| 31 | return new GenericSymbol(this, cloner);
|
---|
| 32 | }
|
---|
| 33 | public GenericSymbol(char s, int minArity, int maxArity)
|
---|
| 34 | : base(s.ToString(), string.Empty) {
|
---|
| 35 | this.minimumArity = minArity;
|
---|
| 36 | this.maximumArity = maxArity;
|
---|
| 37 | }
|
---|
| 38 | }
|
---|
| 39 |
|
---|
| 40 | [StorableConstructor]
|
---|
| 41 | public GenericSymbExprGrammar(bool deserializing) : base(deserializing) { }
|
---|
| 42 |
|
---|
| 43 | public GenericSymbExprGrammar(SymbolicExpressionGrammar original, Cloner cloner) : base(original, cloner) { }
|
---|
| 44 |
|
---|
| 45 | public GenericSymbExprGrammar(IGrammar grammar)
|
---|
| 46 | : base(ItemAttribute.GetName(typeof(GenericSymbExprGrammar)), ItemAttribute.GetDescription(typeof(GenericSymbExprGrammar))) {
|
---|
| 47 |
|
---|
| 48 | var ntSymbs = new List<GenericSymbol>();
|
---|
| 49 | var tSymbs = new List<GenericSymbol>();
|
---|
| 50 | // for terminal and nonterminal symbol in the grammar create a symbol class
|
---|
| 51 | // for non-terminals set the arity and the allowed children
|
---|
| 52 | // for terminals set arity to 0 and allowed children to empty
|
---|
| 53 | foreach (var nt in grammar.NonTerminalSymbols) {
|
---|
| 54 | var ntSymb = CreateSymbol(grammar, nt);
|
---|
| 55 | AddSymbol(ntSymb);
|
---|
| 56 | SetSubtreeCount(ntSymb, ntSymb.MinimumArity, ntSymb.MaximumArity);
|
---|
| 57 | ntSymbs.Add(ntSymb);
|
---|
| 58 | }
|
---|
| 59 | foreach (var t in grammar.TerminalSymbols) {
|
---|
| 60 | var tSymb = new GenericSymbol(t, 0, 0);
|
---|
| 61 | AddSymbol(tSymb);
|
---|
| 62 | SetSubtreeCount(tSymb, 0, 0);
|
---|
| 63 | tSymbs.Add(tSymb);
|
---|
| 64 | }
|
---|
| 65 |
|
---|
| 66 | Func<char, GenericSymbol> findSymb = (char s) => {
|
---|
| 67 | var selectedSymb = ntSymbs.SingleOrDefault(symb => symb.Name == s.ToString());
|
---|
| 68 | if (selectedSymb != null) return selectedSymb;
|
---|
| 69 | return tSymbs.SingleOrDefault(symb => symb.Name == s.ToString());
|
---|
| 70 | };
|
---|
| 71 |
|
---|
| 72 | // set the sentence symbol as the allowed start symbol
|
---|
| 73 | AddAllowedChildSymbol(StartSymbol, findSymb(grammar.SentenceSymbol));
|
---|
| 74 |
|
---|
| 75 | foreach (var nt in ntSymbs) {
|
---|
| 76 | // either all alts are only a single symbol
|
---|
| 77 | // or all alts only use a single symbol (see assertion in CreateSymbol)
|
---|
| 78 | var alts = grammar.GetAlternatives(nt.Name[0]); // all symbols only have a single character name
|
---|
| 79 | Debug.Assert(alts.All(alt => alt.Length == 1 || alt.Distinct().Count() == 1));
|
---|
| 80 |
|
---|
| 81 | foreach (var alt in alts) {
|
---|
| 82 | Debug.Assert(alt.All(ch => ch == alt[0]));
|
---|
| 83 | AddAllowedChildSymbol(nt, findSymb(alt.First()));
|
---|
| 84 | }
|
---|
| 85 | }
|
---|
| 86 | }
|
---|
| 87 |
|
---|
| 88 | private GenericSymbol CreateSymbol(IGrammar g, char s) {
|
---|
| 89 |
|
---|
| 90 | var minArity = g.GetAlternatives(s).Select(alt => alt.Length).Min();
|
---|
| 91 | var maxArity = g.GetAlternatives(s).Select(alt => alt.Length).Max();
|
---|
| 92 | // either the min and max arity is 1 or the alternatives all use the same symbol (hl doesn't know about dependencies between positions in the alternative
|
---|
| 93 | Debug.Assert(
|
---|
| 94 | (minArity == 1 && maxArity == 1) ||
|
---|
| 95 | g.GetAlternatives(s).Select(alt => alt.Distinct()).All(alt => alt.Count() == 1));
|
---|
| 96 | var symb = new GenericSymbol(s, minArity, maxArity);
|
---|
| 97 | return symb;
|
---|
| 98 | }
|
---|
| 99 |
|
---|
| 100 | public override IDeepCloneable Clone(Cloner cloner) {
|
---|
| 101 | return new GenericSymbExprGrammar(this, cloner);
|
---|
| 102 | }
|
---|
| 103 | }
|
---|
| 104 | }
|
---|