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 | }
|
---|