Skip to content
Snippets Groups Projects
RandomGrammarFactory.cpp 3.21 KiB
Newer Older
  • Learn to ignore specific revisions
  • /*
     * RandomGrammarFactory.cpp
     *
     *  Created on: 27. 3. 2014
     *	  Author: Tomas Pecka
     */
    
    #include "RandomGrammarFactory.h"
    
    #include <exception/CommonException.h>
    
    #include <grammar/Grammar.h>
    
    #include <algorithm>
    
    #include <random>
    
    #include <registration/AlgoRegistration.hpp>
    
    
    namespace grammar {
    
    namespace generate {
    
    
    grammar::CFG < > RandomGrammarFactory::generateCFG( ext::set<DefaultSymbolType> nonterminals, ext::set<DefaultSymbolType> terminals, double density ) {
    
    	ext::deque<DefaultSymbolType> terminals2(terminals.begin(), terminals.end());
    	ext::deque<DefaultSymbolType> nonterminals2(nonterminals.begin(), nonterminals.end());
    
    	return RandomGrammarFactory::randomCFG( nonterminals2, terminals2, density );
    }
    
    
    Jan Trávníček's avatar
    Jan Trávníček committed
    grammar::CFG < > RandomGrammarFactory::generateCFG( size_t nonterminalsCount, size_t terminalsCount, bool randomizedAlphabet, double density ) {
    
    	if(terminalsCount > 26)
    
    		throw exception::CommonException("Too big terminals count.");
    
    	ext::vector<DefaultSymbolType> symbols;
    
    	for(int i = 0; i < 26; i++) symbols.push_back(DefaultSymbolType((char)(i + 'a')));
    
    	if(randomizedAlphabet) shuffle(symbols.begin(), symbols.end(), ext::random_devices::semirandom);
    
    	ext::deque<DefaultSymbolType> terminals(symbols.begin(), symbols.begin() + terminalsCount);
    
    
    	if(nonterminalsCount > 26)
    
    		throw exception::CommonException("Too big nonterminals count.");
    
    	ext::vector<DefaultSymbolType> symbols2;
    
    	for(int i = 0; i < 26; i++) symbols2.push_back(DefaultSymbolType((char)(i + 'A')));
    
    	if(randomizedAlphabet) shuffle(symbols2.begin(), symbols2.end(), ext::random_devices::semirandom);
    
    	ext::deque<DefaultSymbolType> nonterminals(symbols2.begin(), symbols2.begin() + nonterminalsCount);
    
    
    	return RandomGrammarFactory::randomCFG( nonterminals, terminals, density );
    }
    
    
    grammar::CFG < > RandomGrammarFactory::randomCFG( const ext::deque<DefaultSymbolType>& nonterminals, const ext::deque<DefaultSymbolType> & terminals, double density ) {
    
    	if( terminals.size( ) <= 0 )
    
    		throw exception::CommonException( "Terminals count must be greater than 0." );
    
    
    	if( nonterminals.size( ) <= 0 )
    
    		throw exception::CommonException( "Nonterminals count must be greater than 0." );
    
    Jan Trávníček's avatar
    Jan Trávníček committed
    	grammar::CFG < > grammar(nonterminals.front());
    
    	grammar.setTerminalAlphabet({terminals.begin(), terminals.end()});
    	grammar.setNonterminalAlphabet({nonterminals.begin(), nonterminals.end()});
    
    
    	if(ext::random_devices::semirandom() % 2)
    
    		grammar.addRule(grammar.getInitialSymbol(), {});
    
    	int rules = 0;
    	while(rules < terminals.size() * nonterminals.size() * density / 100) {
    
    		const DefaultSymbolType& lhs = nonterminals[ext::random_devices::semirandom() % nonterminals.size()];
    
    		int rhsSize = ext::random_devices::semirandom() % 5;
    
    		ext::vector<DefaultSymbolType> rhs;
    
    		int nonterminalsOnRHS = 0;
    		for(int i = 0; i < rhsSize; i++) {
    
    			if(ext::random_devices::semirandom() % (nonterminals.size() + terminals.size()) < nonterminals.size()) {
    				rhs.push_back(nonterminals[ext::random_devices::semirandom() % nonterminals.size()]);
    
    				nonterminalsOnRHS++;
    			} else {
    
    				rhs.push_back(terminals[ext::random_devices::semirandom() % terminals.size()]);
    
    			}
    		}
    		rules += nonterminalsOnRHS;
    		grammar.addRule(lhs, rhs);
    	}
    
    	return grammar;
    }
    
    } /* namespace generate */
    
    } /* namespace grammar */