Algorithms Library Toolkit
A toolkit for algorithms, especially for algorithms on formal languages
GenerateUpToLength.h
Go to the documentation of this file.
1
6#pragma once
7
8#include <grammar/Grammar.h>
9#include <string/LinearString.h>
10#include <alib/set>
11#include <alib/deque>
12#include <alib/trie>
13#include <ext/iterator>
14
20
21#include <grammar/RawRules.h>
22
23namespace grammar {
24
25namespace generate {
26
31 template < class TerminalSymbolType >
32 static bool pruneTrie ( ext::trie < TerminalSymbolType, bool > & trie ) {
33 for ( typename std::map < TerminalSymbolType, ext::trie < TerminalSymbolType, bool > >::iterator iter = trie.getChildren ( ).begin ( ); iter != trie.getChildren ( ).end ( ); )
34 if ( pruneTrie ( iter->second ) )
35 iter = trie.erase ( iter );
36 else
37 ++ iter;
38
39 return trie.getData ( ) == false && trie.getChildren ( ).empty ( );
40 }
41
42public:
55 template < class T, class TerminalSymbolType = typename grammar::TerminalSymbolTypeOfGrammar < T >, class NontermimnalSymbolType = typename grammar::NonterminalSymbolTypeOfGrammar < T > >
56 static ext::trie < TerminalSymbolType, bool > generate ( const T & grammar, unsigned length );
57};
58
59template < class T, class TerminalSymbolType, class NonterminalSymbolType >
62
64 if ( grammar.getGeneratesEpsilon ( ) ) {
65 res.getData ( ) = true; // TODO improve interface
67 }
68
69 struct Node {
71 std::shared_ptr < Node > m_parent;
72 unsigned m_depth;
73
74 Node ( ext::variant < TerminalSymbolType, NonterminalSymbolType > symbol, std::shared_ptr < Node > parent, unsigned depth ) : m_symbol ( std::move ( symbol ) ), m_parent ( std::move ( parent ) ), m_depth ( depth ) {
75 }
76 };
77
78 ext::deque < std::tuple < typename ext::trie < TerminalSymbolType, bool > *, unsigned, std::shared_ptr < Node > > > data;
79 data.push_back ( std::make_tuple ( & res, 0, std::make_shared < Node > ( grammar.getInitialSymbol ( ), nullptr, 1 ) ) );
80
81 while ( ! data.empty ( ) ) {
82 unsigned generatedLen = std::get < 1 > ( data.back ( ) );
83 typename ext::trie < TerminalSymbolType, bool > * trieNode = std::get < 0 > ( data.back ( ) );
84
85 std::shared_ptr < Node > stackTop = std::get < 2 > ( data.back ( ) );
87 unsigned stackSize = stackTop->m_depth - 1;
88 stackTop = stackTop->m_parent;
89
90 data.pop_back ( );
91
92 if ( ! top.template is < NonterminalSymbolType > ( ) ) // maybe not needed
93 continue;
94 auto rule = rules.find ( top.template get < NonterminalSymbolType > ( ) );
95 if ( rule == rules.end ( ) )
96 continue;
97
98 for ( const ext::vector < ext::variant < TerminalSymbolType, NonterminalSymbolType > > & rhs : rule->second ) {
99 if ( generatedLen + stackSize + rhs.size ( ) > length )
100 continue;
101
102 std::shared_ptr < Node > newStackTop = stackTop;
104 newStackTop = std::make_shared < Node > ( symbol, newStackTop, newStackTop ? newStackTop->m_depth + 1 : 1 );
105
106 typename ext::trie < TerminalSymbolType, bool > * newTrieNode = trieNode;
107 unsigned newGeneratedLen = generatedLen;
108 while ( newStackTop != nullptr && grammar.getTerminalAlphabet ( ).count ( newStackTop->m_symbol ) ) {
109 newTrieNode->insert ( newStackTop->m_symbol.template get < TerminalSymbolType > ( ), ext::trie < TerminalSymbolType, bool > ( false ) );
110 newTrieNode = & newTrieNode->getChildren ( ).at ( newStackTop->m_symbol.template get < TerminalSymbolType > ( ) );
111 newStackTop = newStackTop->m_parent;
112 newGeneratedLen += 1;
113 }
114
115 if ( newStackTop == nullptr ) {
116 newTrieNode->getData ( ) = true;
117 } else {
118 data.push_back ( std::make_tuple ( newTrieNode, newGeneratedLen, newStackTop ) );
119 }
120 }
121 }
122
123 pruneTrie ( res );
124
125 return res;
126}
127
128} /* namespace generate */
129
130} /* namespace grammar */
131
Class extending the deque class from the standard library. Original reason is to allow printing of th...
Definition: deque.hpp:44
Class extending the map class from the standard library. Original reason is to allow printing of the ...
Definition: map.hpp:48
auto end() &
Inherited behavior of end for non-const instance.
Definition: map.hpp:215
size_t erase(const K &key)
Erase by key of arbitrary type.
Definition: map.hpp:340
Class introducing a trie with interface trying to be close to the interface of standard library conta...
Definition: trie.hpp:47
children_iterator erase(const_children_iterator position)
Erases a subtrie from a trie on given by position.
Definition: trie.hpp:357
ext::map< Key, trie > & getChildren()
Getter of children of the root node.
Definition: trie.hpp:115
Value & getData()
Getter of the value in the root node.
Definition: trie.hpp:95
const_children_iterator insert(Key key, trie< Key, Value > &&value)
Inserts a subtrie into a trie.
Definition: trie.hpp:152
Implementation of the variant class allowing to store any type of those listed in the template parame...
Definition: variant.hpp:98
Class extending the vector class from the standard library. Original reason is to allow printing of t...
Definition: vector.hpp:45
static ext::map< NonterminalSymbolType, ext::set< ext::vector< ext::variant< TerminalSymbolType, NonterminalSymbolType > > > > getRawRules(const LG< TerminalSymbolType, NonterminalSymbolType > &grammar)
Definition: RawRules.h:92
Definition: GenerateUpToLength.h:30
static ext::trie< TerminalSymbolType, bool > generate(const T &grammar, unsigned length)
Definition: GenerateUpToLength.h:60
return res
Definition: MinimizeByPartitioning.h:145
reverser< T > make_reverse(T &&container)
Reverese adaptor construction function.
Definition: iterator.hpp:544
constexpr auto make_tuple(Elements &&... args)
Helper of extended tuple construction. The tuple is constructed from values pack, types are deduced.
Definition: tuple.hpp:203
Definition: ToAutomaton.h:24