public CNFGrammar(IEnumerable <Production> productions, Nonterminal start) { this.Start = start; foreach (var production in productions) { if (production.Lhs == start && production.Rhs.Count == 0) { if (production.Weight == 0.0) { continue; } if (_emptyProductions.Count == 0) { _emptyProductions.Add(production); } else { _emptyProductions.First().Weight += production.Weight; } } else if (production.IsCnfNonterminal) { _nonterminalProductions.Add(production); } else { _terminalProductions.Add(production); } } SimplifyWithoutInvalidate(); BuildLookups(); BuildHelpers(); }
// TODO: need to check that this is unbiased internal Sentence ProduceNonterminal(Nonterminal nt) { Sentence result = null; var productions = ProductionsFrom(nt); if (productions.Count() == 0) { throw new Exception(string.Format("Can't produce nonterminal {0}; no productions with it on LHS", nt)); } var totalWeight = productions.Sum(w => w.Weight); var targetValue = totalWeight * _rand.NextDouble(); var currentWeight = 0.0; foreach (var production in productions) { currentWeight += production.Weight; if (currentWeight < targetValue) { continue; } result = new Sentence(production.Rhs); break; } Debug.Assert(result != null); return(result); }
public static Nonterminal Of(string v) { Nonterminal nonterminal; if (!_history.TryGetValue(v, out nonterminal)) { nonterminal = new Nonterminal(v); _history[v] = nonterminal; } return nonterminal; }
/// <summary> /// Eliminate the start symbol from right-hand sides /// </summary> /// <param name="productions"></param> private void StepStart(ISet<Production> productions) { var fresh = GetFresh(); productions.Add( // new Production(fresh, new Sentence { Nonterminal.Of("S") }) new Production(fresh, new Sentence { _grammar.Start }) ); _startSymbol = fresh; }
public static Nonterminal Of(string v) { Nonterminal nonterminal; if (!_history.TryGetValue(v, out nonterminal)) { nonterminal = new Nonterminal(v); _history[v] = nonterminal; } return(nonterminal); }
/// <summary> /// Returns a new production. /// </summary> public Production(Nonterminal lhs, Sentence rhs, double weight = 1.0) { if (lhs == null) { throw new ArgumentNullException("Lhs must be non-null"); } if (rhs == null) { throw new ArgumentNullException("Rhs must be non-null"); } this.Lhs = lhs; _rhs = rhs; this.Weight = weight; }
// todo: horrible private Nonterminal GetFresh() { var originalNonterminals = _grammar.GetNonterminals(); Nonterminal result; do { result = Nonterminal.Of("X_" + _freshx); _freshx++; } while (originalNonterminals.Contains(result)); return(result); }
/// <summary> /// Eliminate the start symbol from right-hand sides /// </summary> /// <param name="productions"></param> private void StepStart(ISet <Production> productions) { var fresh = GetFresh(); productions.Add( // new Production(fresh, new Sentence { Nonterminal.Of("S") }) new Production(fresh, new Sentence { _grammar.Start }) ); _startSymbol = fresh; }
public Production NextCNFNonterminalProduction(int numNonTerminals, Nonterminal lhs = null) { if (lhs == null) { lhs = RandomNonterminal(numNonTerminals); } var rhs1 = RandomNonterminal(numNonTerminals, false); var rhs2 = RandomNonterminal(numNonTerminals, false); return(new Production(lhs, new Sentence { rhs1, rhs2 })); }
/// <summary> /// Tries to find a production lhs -> rhs in the grammar, and returns it if found. /// Returns null if no such production is found. /// </summary> // TODO: Inefficient public Production FindProduction(Nonterminal lhs, Sentence rhs) { var productions = ProductionsFrom(lhs); foreach (var production in productions) { if (production.Rhs.SequenceEqual(rhs)) { return(production); } } return(null); }
/// <summary> /// Tries to estimate the probability of a nonterminal yielding null by generating a bunch randomly and counting. /// </summary> public double EstimateProbabilityNull(Nonterminal nt, long iterations) { long nulls = 0; for (int i = 0; i < iterations; i++) { if (this.ProduceNull(nt)) { nulls++; } } return((double)nulls / iterations); }
private Nonterminal RandomNonterminal(int numNonterminals, bool allowStart = true) { int num; if (allowStart) { num = _rand.Next(0, numNonterminals); } else { num = _rand.Next(1, numNonterminals); } return(Nonterminal.Of("X_" + num)); }
/// <summary> /// Turns a string like /// <X> -> <X> 'a' <X> /// into a production. /// Nonterminals must be surrounded by angled brackets, terminals must be surrounded by single quotes, and everything must be separated by spaces. /// </summary> /// <param name="s"></param> /// <returns></returns> public static Production Production(string s) { var match = ProductionRegex.Match(s); if (!match.Success) { throw new Exception("Didn't find valid string"); } var lhsMatch = match.Groups["lhs"]; var ntMatch = match.Groups["nt"]; var tMatch = match.Groups["t"]; var weightMatch = match.Groups["weight"]; if (!lhsMatch.Success) { throw new Exception("Didn't find LHS"); } double weight; if (!double.TryParse(weightMatch.Value, out weight)) { weight = 1.0; } var rhsList = new SortedList <int, Word>(); foreach (Capture capture in ntMatch.Captures) { var word = Nonterminal.Of(capture.Value); rhsList.Add(capture.Index, word); } foreach (Capture capture in tMatch.Captures) { var word = Terminal.Of(capture.Value); rhsList.Add(capture.Index, word); } var rhs = new Sentence(rhsList.Values); var lhs = Nonterminal.Of(lhsMatch.Value); var retval = new Production(lhs, rhs, weight); return(retval); }
public Grammar(IEnumerable <Production> productions, Nonterminal start) : base(start) { _productions = new List <Production>(productions); // if (simplify) { SimplifyWithoutInvalidate(); //} _table = Cache.Create(() => Helpers.BuildLookup( () => _productions, (p) => p.Lhs, (p) => p, () => (ICollection <Production>) new List <Production>(), (x, y) => x.Add(y) )); this.Caches.Add(_table); BuildHelpers(); }
public Grammar(IEnumerable<Production> productions, Nonterminal start) { _productions = new List<Production>(productions); this.Start = start; // if (simplify) { SimplifyWithoutInvalidate(); //} _table = Cache.Create(() => Helpers.BuildLookup( () => _productions, (p) => p.Lhs, (p) => p, () => (ICollection<Production>)new List<Production>(), (x, y) => x.Add(y) )); this.Caches.Add(_table); BuildHelpers(); }
/// <summary> /// Returns a new production. /// </summary> public Production(Nonterminal lhs, Sentence rhs, double weight = 1.0, Annotations annotations = null) { if (lhs == null) { throw new ArgumentNullException("Lhs must be non-null"); } if (rhs == null) { throw new ArgumentNullException("Rhs must be non-null"); } this.Lhs = lhs; Rhs = rhs; this.Weight = weight; if (annotations == null) { annotations = Annotations.Empty; } Annotations = annotations; }
/// <summary> /// Produces a random sentence and returns whether or not it was null /// </summary> /// <returns></returns> private bool ProduceNull(Nonterminal nt) { var sentence = new Sentence { nt }; while (sentence.Count > 0) { for (int i = sentence.Count - 1; i >= 0; i--) { var word = sentence[i]; var newStuff = ProduceNonterminal((Nonterminal)word); if (!newStuff.OnlyNonterminals()) { return(false); } sentence.RemoveAt(i); sentence.InsertRange(i, newStuff); } } return(true); }
public ValueUnitProduction(Nonterminal lhs, Nonterminal rhs) { this.Lhs = lhs; this.Rhs = rhs; }
internal override IEnumerable<Production> ProductionsFrom(Nonterminal lhs) { return _productionsFrom.Value.LookupEnumerable(lhs); }
public CNFGrammar(IEnumerable<Production> productions, Nonterminal start) { this.Start = start; foreach (var production in productions) { if (production.Lhs == start && production.Rhs.Count == 0) { if (production.Weight == 0.0) { continue; } if (_emptyProductions.Count == 0) { _emptyProductions.Add(production); } else { _emptyProductions.First().Weight += production.Weight; } } else if (production.IsCnfNonterminal) { _nonterminalProductions.Add(production); } else { _terminalProductions.Add(production); } } SimplifyWithoutInvalidate(); BuildLookups(); BuildHelpers(); }
public Production(string lhsName, Word rhsOnlyWord, double weight = 1.0) : this(Nonterminal.Of(lhsName), new Sentence(rhsOnlyWord), weight) { }
public Production(Nonterminal lhs, Word rhsOnlyWord, double weight = 1.0) : this(lhs, new Sentence(rhsOnlyWord), weight) { }
public Production(string lhsName, Sentence rhs, double weight = 1.0) : this(Nonterminal.Of(lhsName), rhs, weight) { }
internal abstract IEnumerable <Production> ProductionsFrom(Nonterminal lhs);
internal override IEnumerable <Production> ProductionsFrom(Nonterminal lhs) { return(_table.Value.LookupEnumerable(lhs)); }
public Production NextCNFNonterminalProduction(int numNonTerminals, Nonterminal lhs = null) { if (lhs == null) { lhs = RandomNonterminal(numNonTerminals); } var rhs1 = RandomNonterminal(numNonTerminals, false); var rhs2 = RandomNonterminal(numNonTerminals, false); return new Production(lhs, new Sentence { rhs1, rhs2 }); }
public BaseGrammar(Nonterminal start) { Start = start; }