Free cookie consent management tool by TermsFeed Policy Generator

Ignore:
Timestamp:
02/09/15 09:48:30 (10 years ago)
Author:
gkronber
Message:

#2283 new experiments

File:
1 edited

Legend:

Unmodified
Added
Removed
  • branches/HeuristicLab.Problems.GrammaticalOptimization/HeuristicLab.Common/ExpressionExtender.cs

    r11966 r11972  
    4949    }
    5050
    51     // an expression is a list of terms
     51    // an expression is a sorted set of terms
    5252    // a term is an (ordered) list of factors
    53     // a factor is a symbol or an inverted expression
     53    // a factor is either a single symbol or an inverted expression
    5454    // CanonicalExpression reads multiple terms (expressions) and must merge the terms in the expression (ordering and duplicates)
    5555    // CanonicalTerm reads multiple factors and must expand factors whenever it reads a combined factor (expression) it produces an expression
     
    8383    // canonical term returns either a single term (product of factors) or a set of terms
    8484    private Expr CanonicalTerm() {
    85       var factors = new List<Expr>();
    86       var invFactors = new List<Expr>();
     85      var factors = new List<Factor>();
    8786      var f = CanonicalFact();
    8887      if (f != null) factors.Add(f);
     
    9796          f = CanonicalFact();
    9897          f.Invert();
    99           if (f != null) invFactors.Add(f);
     98          if (f != null) factors.Add(f);
    10099        }
    101100        curSy = CurSy();
    102101      }
    103 
    104       // cancellation
    105       foreach (var invF in invFactors.ToArray()) {
    106         invF.Invert();
    107         if (factors.Contains(invF)) {
    108           invFactors.Remove(invF);
    109           factors.Remove(invF);
    110           if (factors.Count == 0) factors.Add(new Expr(new Term('1')));
    111         } else invF.Invert();
    112       }
    113 
    114       return ExpandFactors(factors, invFactors);
    115     }
    116 
    117     private Expr ExpandFactors(List<Expr> factors, List<Expr> invFactors) {
     102      return ExpandFactors(factors);
     103    }
     104
     105    /*
     106    private List<Factor> CancelFactors(Term t) {
     107      var nonInvF = t.Factors.Where(f => !f.IsInverse).ToArray();
     108      var invF = t.Factors.Where(f => f.IsInverse).ToArray();
     109
     110      var result = new List<Factor>();
     111      foreach (var f in nonInvF) {
     112        if (!invF.Contains(f)) {
     113          result.Add(f);
     114        }
     115      }
     116      if (result.Count == 0) result.Add(new Factor('1'));
     117      return result;
     118    }
     119    */
     120    // canonical fact returns a factor (either a singe variable, or a set of terms)
     121    private Factor CanonicalFact() {
     122      var curSy = CurSy();
     123      if (curSy == '!') {
     124        throw new NotSupportedException();
     125      } else if (curSy == '(') {
     126        NewSy();
     127        Expr r = CanonicalExpr(); // this is already simplified
     128        if (CurSy() != ')') throw new ArgumentException();
     129        NewSy();
     130        return new Factor(r);
     131      } else if (curSy >= 'a' && curSy <= 'z') {
     132        NewSy();
     133        return new Factor(curSy);
     134        //       } else if (curSy >= '0' && curSy <= '9') {
     135      } else if (curSy >= 'A' && curSy <= 'Z') {
     136        // treat nonterminals in the same way as variables
     137        NewSy();
     138        return new Factor(curSy);
     139
     140      } else throw new ArgumentException("found symbol " + curSy);
     141    }
     142
     143    // a list of factors (symbols, or expressions, and possibly inverses are read
     144    // a lis to factors symbols or expressions and possibly inverses are produced
     145    // all non-inverse expression factors are expanded
     146    private Expr ExpandFactors(IEnumerable<Factor> factors) {
    118147      // if (invFactors.Count > 0) throw new NotImplementedException();
    119       Expr currentFact = factors.First(); // new Expr(simpleFactor));
    120       Debug.Assert(!currentFact.Inverse); // the first factor is never an inverted factor
     148      Debug.Assert(!factors.First().IsInverse); // the first factor is never an inverted factor
     149
     150      // each factor could be a list of terms (expression)
     151
     152      Expr currentFact = null;
     153      var firstFactor = factors.First();
     154      if (firstFactor.IsSimpleFactor) currentFact = new Expr(new Term(firstFactor));
     155      else currentFact = firstFactor.Expr;
     156
    121157      foreach (var fact in factors.Skip(1)) {
    122         currentFact = AllProducts(currentFact, fact);
    123       }
    124       foreach (var invF in invFactors) {
    125         currentFact = AllInvProducts(currentFact, invF);
     158        Expr curExpr = null;
     159        if (fact.IsSimpleFactor || fact.IsInverse) curExpr = new Expr(new Term(fact));
     160        else curExpr = fact.Expr;
     161        currentFact = AllProducts(currentFact, curExpr);
    126162      }
    127163      return currentFact;
     
    133169      var combs = from aT in aTerms
    134170                  from bT in bTerms
    135                   select new Term(aT.Symbols.Concat(bT.Symbols), aT.InvExpressions.Concat(bT.InvExpressions));
     171                  let factors = CancelFactors(aT.Factors.Concat(bT.Factors))
     172                  select new Term(factors);
    136173      return new Expr(combs);
    137174    }
    138175
    139     private Expr AllInvProducts(Expr a, Expr b) {
    140       var aTerms = a.Terms.ToArray();
    141       var combs = from aT in aTerms
    142                   select new Term(aT.Symbols, aT.InvExpressions.Concat(new Expr[] { b }));
    143       return new Expr(combs);
    144     }
    145 
    146     // canonical fact returns a factor (either a singe variable, or a set of terms)
    147     private Expr CanonicalFact() {
    148       var curSy = CurSy();
    149       if (curSy == '!') {
    150         throw new NotSupportedException();
    151       } else if (curSy == '(') {
    152         NewSy();
    153         Expr r = CanonicalExpr();
    154         if (CurSy() != ')') throw new ArgumentException();
    155         NewSy();
    156         return r;
    157       } else if (curSy >= 'a' && curSy <= 'z') {
    158         NewSy();
    159         return new Expr(new Term(curSy));
    160         //       } else if (curSy >= '0' && curSy <= '9') {
    161       } else if (curSy >= 'A' && curSy <= 'Z') {
    162         // treat nonterminals in the same way as variables
    163         NewSy();
    164         return new Expr(new Term(curSy));
    165 
    166       } else throw new ArgumentException("found symbol " + curSy);
     176    private IEnumerable<Factor> CancelFactors(IEnumerable<Factor> factors) {
     177      var factorsArr = factors.ToArray();
     178      var results = new List<Factor>(factors);
     179      foreach (var f in factorsArr) {
     180        if (f.ToString() == "1") results.Remove(f);
     181        if (f.IsInverse) {
     182          // find matching
     183          Factor match;
     184          if (f.IsSimpleFactor) match = factorsArr.FirstOrDefault(other => !other.IsInverse && f.Symbol.Equals(other.Symbol));
     185          else match = factorsArr.FirstOrDefault(other => !other.IsInverse && f.Expr.Equals(other.Expr));
     186          if (match != null) {
     187            results.Remove(match);
     188            results.Remove(f);
     189          }
     190        }
     191      }
     192      if (results.Count == 0) results.Add(new Factor('1'));
     193      return results;
    167194    }
    168195
     
    170197    // term can be merged (essentially an ordered list of factors)
    171198    internal class Term : IComparable<Term> {
    172       private readonly SortedList<char, int> factorSymbs; // factor symbol and the number of occurrences
    173       private readonly SortedList<Expr, int> invExpressions;
    174 
    175       public IEnumerable<char> Symbols {
     199      private readonly SortedList<Factor, int> factors; // factor symbol and the number of occurrences
     200
     201      public IEnumerable<Factor> Factors {
    176202        get {
    177           return factorSymbs.SelectMany(p => Enumerable.Repeat(p.Key, p.Value));
    178         }
    179       }
    180 
    181       public IEnumerable<Expr> InvExpressions {
    182         get {
    183           if (invExpressions == null) return Enumerable.Empty<Expr>();
    184           return invExpressions.Where(p => p.Value > 0).SelectMany(p => Enumerable.Repeat(p.Key, p.Value));
    185         }
    186       }
    187 
    188       public Term(char f) {
    189         factorSymbs = new SortedList<char, int>(new FactorComparer());
    190         factorSymbs.Add(f, 1);
    191       }
    192       public Term(IEnumerable<char> factors, IEnumerable<Expr> invFactors) {
    193         factorSymbs = new SortedList<char, int>(new FactorComparer());
    194         invExpressions = new SortedList<Expr, int>();
     203          return factors.SelectMany(p => Enumerable.Repeat(p.Key, p.Value));
     204        }
     205      }
     206
     207      public Term(Factor f) {
     208        factors = new SortedList<Factor, int>();
     209        factors.Add(f, 1);
     210      }
     211      public Term(IEnumerable<Factor> factors) {
     212        this.factors = new SortedList<Factor, int>();
    195213        foreach (var f in factors) {
    196           if (factorSymbs.ContainsKey(f)) factorSymbs[f] += 1;
    197           else factorSymbs.Add(f, 1);
    198         }
    199 
    200         foreach (var invF in invFactors) {
    201           if (invF.Terms.Count == 1) {
    202             var t = invF.Terms.First();
    203             foreach (var f in factors.Concat(new char[] { '1' })) {
    204               if (t.factorSymbs.ContainsKey(f)) {
    205                 t.factorSymbs[f] -= 1;
    206                 if (t.factorSymbs[f] == 0) t.factorSymbs.Remove(f);
    207               }
    208             }
    209           }
    210           if (invExpressions.ContainsKey(invF)) invExpressions[invF] += 1;
    211           else invExpressions.Add(invF, 1);
     214          if (this.factors.ContainsKey(f)) this.factors[f] += 1;
     215          else this.factors.Add(f, 1);
    212216        }
    213217      }
    214218
    215219      public int CompareTo(Term other) {
    216         if (ContainsNonTerminal(Symbols) && !ContainsNonTerminal(other.Symbols)) {
     220        if (ContainsNonTerminal(Factors) && !ContainsNonTerminal(other.Factors)) {
    217221          return 1;
    218         } else if (!ContainsNonTerminal(Symbols) && ContainsNonTerminal(other.Symbols)) {
     222        } else if (!ContainsNonTerminal(Factors) && ContainsNonTerminal(other.Factors)) {
    219223          return -1;
    220224        } else {
    221           var countComp = Symbols.Count().CompareTo(other.Symbols.Count());
     225          var countComp = Factors.Count().CompareTo(other.Factors.Count());
    222226          if (countComp != 0) return countComp;
    223           return string.Join("", Symbols).CompareTo(string.Join("", other.Symbols));
     227          return string.Join("", Factors).CompareTo(string.Join("", other.Factors));
    224228        }
    225229      }
    226230
    227231      public override string ToString() {
    228         if (InvExpressions.Any())
    229           return string.Join("*", Symbols) + "%" + string.Join("%", InvExpressions);
    230         else {
    231           return string.Join("*", Symbols);
    232         }
     232
     233        return string.Join("*", Factors);
    233234      }
    234235      public override bool Equals(object obj) {
    235236        var other = obj as Term;
    236237        if (other == null) return false;
    237         if (this.Symbols.Count() != other.Symbols.Count()) return false;
    238         if (this.InvExpressions.Count() != other.InvExpressions.Count()) return false;
    239         if (this.Symbols.Zip(other.Symbols, Tuple.Create).Any(t => t.Item1 != t.Item2)) return false;
    240         if (this.InvExpressions.Zip(other.InvExpressions, Tuple.Create).Any(t => t.Item1 != t.Item2)) return false;
     238        if (this.Factors.Count() != other.Factors.Count()) return false;
     239        if (this.Factors.Zip(other.Factors, Tuple.Create).Any(t => t.Item1 != t.Item2)) return false;
    241240        return true;
    242241      }
    243242      public override int GetHashCode() {
    244243        var h = 31415;
    245         foreach (var v in Symbols) {
     244        foreach (var v in Factors) {
    246245          h ^= v.GetHashCode();
    247246        }
    248         foreach (var v in InvExpressions) {
    249           h ^= v.GetHashCode();
    250         }
     247        return h;
     248      }
     249    }
     250    #endregion
     251
     252    #region factor
     253    // factors is either a single symbol or an inverted expression
     254    internal class Factor : IComparable<Factor> {
     255      public bool IsSimpleFactor { get { return Expr == null; } }
     256      public char Symbol { get { return symbol; } }
     257      public Expr Expr { get { return expr; } }
     258      public bool IsInverse { get { return inv; } }
     259      private readonly char symbol = '\0';
     260      private readonly Expr expr;
     261      private bool inv;
     262
     263      public Factor(char f) {
     264        this.symbol = f;
     265      }
     266      public Factor(Expr expr) {
     267        this.expr = expr;
     268      }
     269
     270      public void Invert() {
     271        this.inv = !inv;
     272      }
     273
     274      public int CompareTo(Factor other) {
     275        // 1) single symbol factors first
     276        // 2) expression factors by expression compare
     277        var crit1 = ContainsNonTerminal(this).CompareTo(ContainsNonTerminal(other));
     278        if (crit1 != 0) return crit1;
     279
     280        var crit2 = this.IsInverse.CompareTo(other.IsInverse);
     281        if (crit2 != 0) return crit2;
     282
     283        var crit3 = this.IsSimpleFactor.CompareTo(other.IsSimpleFactor);
     284        if (crit3 != 0) return crit3;
     285
     286        // both are simple or expressions
     287        if (IsSimpleFactor) return this.symbol.CompareTo(other.symbol);
     288        else return this.Expr.CompareTo(other.Expr);
     289      }
     290
     291      public override string ToString() {
     292        var s = Expr == null ? symbol.ToString() : "(" + expr.ToString() + ")";
     293        if (IsInverse) {
     294          return "1/" + s;
     295        } else return s;
     296      }
     297      public override bool Equals(object obj) {
     298        var other = obj as Factor;
     299        if (other == null) return false;
     300        if (IsInverse != other.IsInverse) return false;
     301        if (this.symbol != other.symbol) return false;
     302        if (this.Expr != other.Expr) return false;
     303        return true;
     304      }
     305      public override int GetHashCode() {
     306        var h = 31415;
     307        h ^= symbol.GetHashCode();
     308        if (Expr != null) h ^= Expr.GetHashCode();
    251309        return h;
    252310      }
     
    258316    internal class Expr : IComparable<Expr> {
    259317      public readonly SortedSet<Term> Terms; // only set for Kind == Expr
    260       public bool Inverse;
     318      //public bool Inverse;
    261319      public Expr(Term t) {
    262320        Terms = new SortedSet<Term>();
     
    286344
    287345      public override string ToString() {
    288         if (Inverse && Terms.Count > 1)
    289           return "(" + string.Join("+", Terms) + ")";
    290         else if (Inverse && Terms.Count == 1) {
    291           return Terms.First().ToString().Replace("%", "#").Replace("*", "%").Replace("#", "*");
    292         } else
    293           return string.Join("+", Terms);
     346        // if (Inverse && Terms.Count > 1)
     347        //   return "(" + string.Join("+", Terms) + ")";
     348        // else if (Inverse && Terms.Count == 1) {
     349        //   return Terms.First().ToString().Replace("%", "#").Replace("*", "%").Replace("#", "*");
     350        // } else
     351        return string.Join("+", Terms);
    294352      }
    295353      public override bool Equals(object obj) {
    296354        var other = obj as Expr;
    297355        if (other == null) return false;
    298         if (this.Inverse != other.Inverse) return false;
     356        //if (this.Inverse != other.Inverse) return false;
    299357        if (this.Terms.Count() != other.Terms.Count()) return false;
    300358        return this.Terms.Intersect(other.Terms).Count() == this.Terms.Count;
     
    308366        return h;
    309367      }
    310 
    311       public void Invert() {
    312         this.Inverse = !Inverse;
    313       }
    314368    }
    315369    #endregion
     
    317371      return symb >= 'A' && symb <= 'Z';
    318372    }
    319     internal static bool ContainsNonTerminal(IEnumerable<char> symbs) {
    320       return symbs.Any(IsNonTerminal);
    321     }
     373    internal static bool ContainsNonTerminal(IEnumerable<Factor> factors) {
     374      return factors.Any(ContainsNonTerminal);
     375    }
     376    internal static bool ContainsNonTerminal(Factor f) {
     377      if (f.Expr == null) return IsNonTerminal(f.Symbol);
     378      else return ContainsNonTerminal(f.Expr);
     379    }
     380
     381    private static bool ContainsNonTerminal(Expr expr) {
     382      return expr.Terms.Any(ContainsNonTerminal);
     383    }
     384
     385    private static bool ContainsNonTerminal(Term term) {
     386      return ContainsNonTerminal(term.Factors);
     387    }
     388
     389
     390    /*
    322391
    323392    internal class FactorComparer : IComparer<char> {
     
    333402        }
    334403      }
    335     }
     404    }*/
    336405  }
    337406}
Note: See TracChangeset for help on using the changeset viewer.