private static ContextFreeGrammar RemoveNonGeneratingSymbols(ContextFreeGrammar cfg, CancellationToken token) { InitIds(cfg); var res = new HashSet <int>(cfg.GetNonVariableSymbols().Select(v => v.UnqiueId)); var remainingProductions = new Dictionary <int, List <Production> >(); foreach (var s in cfg.Variables) { remainingProductions[s.UnqiueId] = new List <Production>(); } foreach (var prod in cfg.GetProductions()) { remainingProductions[prod.Lhs.UnqiueId].Add(prod); } int oldLength; do { token.ThrowIfCancellationRequested(); oldLength = res.Count; var newSymbols = new HashSet <int>(); foreach (var e in remainingProductions) { token.ThrowIfCancellationRequested(); if (e.Value.Any(p => p.Rhs.All(s => res.Contains(s.UnqiueId)))) { res.Add(e.Key); newSymbols.Add(e.Key); } } foreach (var s in newSymbols) { token.ThrowIfCancellationRequested(); remainingProductions.Remove(s); } }while (res.Count > oldLength); if (!res.Contains(cfg.StartSymbol.UnqiueId)) { return(null); } else { var prods = FilterProductions(res, cfg.GetProductions()); return(new ContextFreeGrammar(cfg.StartSymbol, prods)); } }
public override int Difficulty() { // grammar size (20%) double grammarDif = 20.0; if (grammar.GetProductions().Count() < 8) { grammarDif *= 0.7; //productions } else if (grammar.GetProductions().Count() < 6) { grammarDif *= 0.5; } else if (grammar.GetProductions().Count() < 4) { grammarDif *= 0.1; } if (grammar.Variables.Count() < 4) { grammarDif *= 0.5; //nonterminals } else if (grammar.Variables.Count() < 3) { grammarDif *= 0.1; } // amount of work (50%) double numberOfNeededWordsDif = 50.0 / 3 * (inNeeded - 1) / 3 * (outNeeded - 1); // hard to find solutions (30%) double sparseDif = 30.0; double inPerc = numberOfShortWords * 1.0 / possibleShortWords; double outPerc = 1 - inPerc; double sparsity = Math.Min(inPerc, outPerc); if (sparsity >= 0.3) { sparseDif *= 0; } else if (sparsity >= 0.2) { sparseDif *= 0.2; } else if (sparsity >= 0.1) { sparseDif *= 0.5; } else if (sparsity >= 0.05) { sparseDif *= 0.8; } return((int)Math.Round(grammarDif + numberOfNeededWordsDif + sparseDif)); }
/// <summary> /// Converts the given cfg into a new one in 2NF, that means that every production has at most 2 symbols on the right hand side /// </summary> /// <param name="cfg">cfg</param> /// <returns>cfg in 2NF</returns> public static ContextFreeGrammar To2NF(ContextFreeGrammar cfg) { var productions = new List<Production>(); int currentNumber = 0; var productionsToShorten = new Queue<Production>(cfg.GetProductions()); while (productionsToShorten.Count() > 0) { var next = productionsToShorten.Dequeue(); if (next.Rhs.Length <= 2) { productions.Add(next); } else { var newNonTerminal = new Nonterminal(PrefixOfAddedNonterminals + currentNumber); currentNumber++; Assertion.Assert(!cfg.Variables.Any(v => v.Name.Equals(newNonTerminal.Name)), string.Format("The nonterminal with id {0} already existed. Please ensure, that the CFG does not use ints as ids", newNonTerminal.Name)); productions.Add(new Production(next.Lhs, next.Rhs[0], newNonTerminal)); productionsToShorten.Enqueue(new Production(newNonTerminal, next.Rhs.Skip(1).ToArray())); } } return new ContextFreeGrammar(cfg.StartSymbol, productions); }
public PerformanceCFG(ContextFreeGrammar cfg) { Cfg = cfg; InitIds(); BinaryProductions = Cfg.GetProductions().Where(p => p.Rhs.Count() == 2).ToList(); InitializeProductionsByGrammarSymbolsInRightHandSide(); }
public override int Difficulty() { int inputProd = grammar.GetProductions().Count(); int outputProd = 0; if (sol != null) { outputProd = sol.GetProductions().Count(); } // input grammar size (20%) double inputGrammarDif = 20.0 * Math.Min(inputProd, 10) / 10; // output grammar size (80%) double outputGrammarDif = 80.0 * Math.Min(outputProd, 15) / 15; return((int)Math.Round(inputGrammarDif + outputGrammarDif)); }
public void GrammarDerivationTest1() // basics { String sg = "S->aSb|aaSbb|"; ContextFreeGrammar g1 = GrammarParser <char> .Parse(f1, sg); Assert.IsTrue(Derivation.findAllDerivations(g1.GetProductions(), new GrammarSymbol[] { g1.StartSymbol }).Count == 3); Assert.IsTrue(Derivation.isValidDerivationStep(g1.GetProductions(), new GrammarSymbol[] { g1.StartSymbol }, new GrammarSymbol[] { new Exprinal <char>('a', "a"), g1.StartSymbol, new Exprinal <char>('b', "b") })); Assert.IsTrue(Derivation.isValidDerivationStep(g1.GetProductions(), new GrammarSymbol[] { g1.StartSymbol }, new GrammarSymbol[] { new Exprinal <char>('a', "a"), new Exprinal <char>('a', "a"), g1.StartSymbol, new Exprinal <char>('b', "b"), new Exprinal <char>('b', "b") })); Assert.IsTrue(Derivation.isValidDerivationStep(g1.GetProductions(), new GrammarSymbol[] { g1.StartSymbol }, new GrammarSymbol[] {})); Assert.IsFalse(Derivation.isValidDerivationStep(g1.GetProductions(), new GrammarSymbol[] { g1.StartSymbol }, new GrammarSymbol[] { g1.StartSymbol })); }
public void GrammarDerivationTest() //tests derivation computation in combination with parsing (grammar and derivation) { String sg = "S->S S S | x | A | ab | A -> A A | S | a | "; ContextFreeGrammar g = GrammarParser <char> .Parse(f1, sg); var der1 = DerivationParser <char> .Parse(f1, "S \n A \n A A \n A \n A A \n A S \n A \n S \n S S S \n S a b S \n x a b S \n x a b S S S \n x a b x S S \n x a b x x S \n x a b x x x"); Assert.IsTrue(Derivation.comparator.Equals(der1[0], new GrammarSymbol[] { g.StartSymbol })); //check start for (int i = 1; i < der1.Count; i++) { Assert.IsTrue(Derivation.isValidDerivationStep(g.GetProductions(), der1[i - 1], der1[i])); //check step } }
public override int Difficulty() { int grammarPoints = 20; if (grammar.Variables.Count <= 2) { grammarPoints -= 5; } if (grammar.Variables.Count <= 3) { grammarPoints -= 5; } int nr_prod = grammar.GetProductions().Count(); if (nr_prod <= 8) { grammarPoints -= 5; } if (nr_prod <= 12) { grammarPoints -= 5; } int typePoints = 20; if (derivationType == Derivation.DERIVATION_ALL) { typePoints = 0; } int derivationPoints = 60; if (derivation.Count <= 5) { derivationPoints = 0; } else { derivationPoints = Math.Min(60, 4 * (derivation.Count - 5)); } return(grammarPoints + typePoints + derivationPoints); }
void TestCFGParser_validate(string input) { ContextFreeGrammar cfg = GrammarParser <string> .Parse(MapTerminalToDummyAutomaton, input); Assert.IsNull(cfg.BuiltinTerminalAlgebra); Assert.AreEqual("START", cfg.StartSymbol.Name); Assert.AreEqual(3, cfg.Nonterminals.Count); var terminals = new List <GrammarSymbol>(cfg.GetTerminals()); Assert.AreEqual(3, terminals.Count); var a = new Terminal <string>("(a)"); var b = new Terminal <string>("(b)"); var at = new Terminal <string>("(@)"); Assert.IsTrue(terminals.Contains(a)); Assert.IsTrue(terminals.Contains(b)); Assert.IsTrue(terminals.Contains(at)); var productions = new List <Production>(cfg.GetProductions()); Assert.AreEqual(6, productions.Count); }
private static ContextFreeGrammar RemoveNonReachableSymbols(ContextFreeGrammar cfg, CancellationToken token) { InitIds(cfg); var productions = cfg.productionMap; var res = new HashSet <int>() { cfg.StartSymbol.UnqiueId }; var queue = new Queue <Nonterminal>(); queue.Enqueue(cfg.StartSymbol); while (queue.Count > 0) { token.ThrowIfCancellationRequested(); var next = queue.Dequeue(); var prods = productions[next]; foreach (var prod in prods) { token.ThrowIfCancellationRequested(); foreach (var rhs in prod.Rhs) { if (res.Add(rhs.UnqiueId) && rhs is Nonterminal) { queue.Enqueue((Nonterminal)rhs); } } } } return(new ContextFreeGrammar(cfg.StartSymbol, FilterProductions(res, cfg.GetProductions()))); }
/// <summary> /// adds to the given dictionary recursively all entries, that have a production with all right-hand-side-symbols on the dictionary /// </summary> /// <param name="entries"></param> /// <param name="cfg"></param> internal static void AddChainEntries(Dictionary <int, DerivationNode <A> > entries, ContextFreeGrammar cfg) { bool newProductionsFound = true; while (newProductionsFound) { var productions = cfg.GetProductions().Where(prod => prod.Rhs.All(s => entries.ContainsKey(s.UnqiueId))).ToList(); var newProductions = productions.Where(prod => !entries.ContainsKey(prod.Lhs.UnqiueId)).ToList(); if (newProductions.Count > 0) { foreach (var prod in newProductions) { if (!entries.ContainsKey(prod.Lhs.UnqiueId)) { entries.Add(prod.Lhs.UnqiueId, new DerivationNode <A>(prod, prod.Rhs.Select(s => entries[s.UnqiueId]).ToList())); } } } else { newProductionsFound = false; } } }
public FindDerivationProblem Generate(int targetLevel) { ContextFreeGrammar grammar = GrammarGenerator.GenerateRandom(); var productions = grammar.GetProductions(); var toAdd = new List <Production>(); //make sure every varaible has a resolution (production with #NT = 0) and an continuation (production with #NT > 0) foreach (Nonterminal nt in grammar.Variables) { var nt_prods = grammar.GetProductions(nt); //resolution check var p = nt_prods.ToList().Find(pp => pp.ContainsNoVariables); if (p == null) { GrammarSymbol t = Choose(grammar.GetNonVariableSymbols()); if (t == null) { t = new Exprinal <char>('x', "x"); } p = new Production(nt, new GrammarSymbol[] { t }); toAdd.Add(p); } //continuation check p = nt_prods.ToList().Find(pp => Derivation.countNT(pp.Rhs) >= 1); if (p == null) { //resolution check GrammarSymbol t = Choose(grammar.Variables); p = new Production(nt, new GrammarSymbol[] { Choose(grammar.Variables), Choose(grammar.Variables) }); toAdd.Add(p); } } //add new productions (for resolution and continuation) if (toAdd.Count != 0) { grammar = new ContextFreeGrammar(grammar.StartSymbol, grammar.GetProductions().Concat(toAdd)); } productions = grammar.GetProductions(); //type bool shouldBeAny = true; if (targetLevel == Generation.ANY) { shouldBeAny = (rnd.Next(0, 9) < 3); // 30% } if (targetLevel == Generation.MEDIUM) { shouldBeAny = (rnd.Next(0, 9) < 2); // 20% } if (targetLevel == Generation.HIGH) { shouldBeAny = (rnd.Next(0, 9) < 9); // 90% } int type = Derivation.DERIVATION_ALL; if (!shouldBeAny) { type = Derivation.DERIVATION_LEFTMOST; if (rnd.Next(0, 9) < 3) { type = Derivation.DERIVATION_RIGHTMOST; } } //nr of steps int steps = rnd.Next(5, 10); if (targetLevel == Generation.LOW) { steps = rnd.Next(3, 6); } if (targetLevel == Generation.MEDIUM) { steps = rnd.Next(7, 9); } if (targetLevel == Generation.HIGH) { steps = rnd.Next(10, 12); } List <GrammarSymbol[]> derivation = new List <GrammarSymbol[]>(steps + 1); var cur = new GrammarSymbol[] { grammar.StartSymbol }; derivation.Add(cur); for (int i = 0; i < steps; i++) { //get possible next steps IEnumerable <GrammarSymbol[]> next = Derivation.findAllDerivations(grammar.GetProductions(), cur, type); if (Derivation.countNT(cur) <= 1 && i != steps - 1) //don't end yet! { next = next.Where(pw => Derivation.countNT(pw) >= 1); } //try not to repeat var next_part = next.Except(derivation); if (next_part.Count() > 0) { next = next_part; } cur = Choose(next); //cut out repeat if (derivation.Contains(cur)) { int r_i = derivation.IndexOf(cur); derivation = derivation.GetRange(0, r_i); } //add next step derivation.Add(cur); } //replace all NTs while (Derivation.countNT(cur) > 0) { //get possible next steps IEnumerable <GrammarSymbol[]> next = Derivation.findAllDerivations(grammar.GetProductions(), cur, type); //filter int curNTs = Derivation.countNT(cur); next = next.Where(pw => Derivation.countNT(pw) < curNTs); cur = Choose(next); derivation.Add(cur); } String word = Derivation.partialWordToString(cur); return(new FindDerivationProblem(grammar, word, type, derivation)); }