コード例 #1
0
        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));
        }
コード例 #3
0
        /// <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);
        }
コード例 #4
0
 public PerformanceCFG(ContextFreeGrammar cfg)
 {
     Cfg = cfg;
     InitIds();
     BinaryProductions = Cfg.GetProductions().Where(p => p.Rhs.Count() == 2).ToList();
     InitializeProductionsByGrammarSymbolsInRightHandSide();
 }
コード例 #5
0
        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));
        }
コード例 #6
0
        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 }));
        }
コード例 #7
0
        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
            }
        }
コード例 #8
0
        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);
        }
コード例 #9
0
        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);
        }
コード例 #10
0
        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())));
        }
コード例 #11
0
        /// <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;
                }
            }
        }
コード例 #12
0
        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));
        }