def test_get_last_tree(self): WordsData(self.WORDS) word_tuple = ( Words( { "word": "古池", "vowel": "ウウイエ", "length": 4, "part": "名詞" } ), Words( { "word": "蛙", "vowel": "アエウ", "length": 3, "part": "名詞" } ), Words( { "word": "あ", "vowel": "ア", "length": 1, "part": "名詞" } ) ) root = PhraseTree.define_root(possible_next_words=list(self.SUCCESS_CHAINS.keys())) next_tree = PhraseTree(current_words=word_tuple) root.next_tree = next_tree self.assertEqual( root.get_last_tree(root), next_tree )
def test_construct_syllable(self): WordsData.words_data = self.SUCCESS_WORDS_TWELVE ChainsData.chains_data = self.SUCCESS_CHAINS_TWELVE haiker = Haiker() root = PhraseTree.define_root( possible_next_words=list(self.SUCCESS_CHAINS_TWELVE.keys())) self.assertIsInstance(haiker.construct_syllable(root, self.TWELVE), PhraseTree) pt = haiker.construct_syllable(root, self.TWELVE) self.assertEqual(PhraseTree.count_phrase_len(pt), self.TWELVE)
def construct_syllable(self, phrase_tree, expected_vowel_len, noun=False): """ 最初の音節を作成する. Args: phrase_tree: PhraseTree クラスオブジェクト expected_vowel_len: 音節の読みの長さ Returns: 音節 """ # phrase_tree には,current と next が格納済み while True: if self._is_empty_first_node(phrase_tree): raise ConstructionError('First node has become empty.') while True: # 単語タプルをランダムに1つ取得 try: PhraseTree.disclose(phrase_tree, "construct ---------") phrase_tree, phrase_tree.next_tree = self._get_word( phrase_tree) PhraseTree.disclose(phrase_tree, "construct 2 ---------") except ValueError: logger.info('*** Cnstruction failed ***') raise if phrase_tree.next_tree is None: break text_vowel_len = PhraseTree.count_phrase_len( phrase_tree.next_tree) if phrase_tree.possible_next_words == list(): try: phrase_tree = self._back_prev_word_list(phrase_tree) except ValueError: logger.info('*** Cnstruction failed ***') raise elif self._is_n_char(expected_vowel_len, text_vowel_len): assert phrase_tree is not None, "phrase_tree is None" self._post_proc(phrase_tree.next_tree) return phrase_tree.next_tree elif self._is_less_than_n_char(expected_vowel_len, text_vowel_len): # 次の単語タプルを取得する前の処理 phrase_tree = phrase_tree.next_tree assert phrase_tree is not None, "phrase_tree is None" break else: # 5文字より長くなったら別の単語を取得しなおす # 現在の next_tree を破棄する pass
def _back_prev_word_list(self, phrase_tree): """ 単語リストが空になったら,前の単語リストに戻る """ if PhraseTree.is_root(phrase_tree): raise ValueError('Impossible to back prev word list') return phrase_tree.parent
def compose(self): """ 俳句を詠む. """ first_loop_limit = 500 first_current_loop = 0 while True: logger.debug('+++ current loop: {} +++'.format(first_current_loop)) first_current_loop += 1 if first_current_loop == first_loop_limit: return "***** だめでした *****" try: root = PhraseTree.define_root( possible_next_words=self._get_word_list()) first_phrase_tree = self.construct_syllable(root, self.FIVE) first_text_list = Phrase.text_list PhraseTree.disclose(first_phrase_tree, "first -------------") except ValueError: logger.debug('***** first ValueError *****') continue try: root = PhraseTree.define_root( possible_next_words=first_phrase_tree.possible_next_words) second_phrase_tree = self.construct_syllable(root, self.SEVEN) second_last_vowel = Phrase.last_vowel second_text_list = Phrase.text_list PhraseTree.disclose(second_phrase_tree, "second -------------") except ValueError: logger.debug('***** second ValueError *****') continue try: root = PhraseTree.define_root( possible_next_words=second_phrase_tree.possible_next_words) third_phrase_tree = self.construct_syllable(root, self.FIVE) third_last_vowel = Phrase.last_vowel third_text_list = Phrase.text_list PhraseTree.disclose(third_phrase_tree, "third -------------") except ValueError: logger.debug('***** third ValueError *****') continue if Rhymer.is_rhymed(second_last_vowel, third_last_vowel): haiku = "".join(first_text_list + second_text_list + third_text_list) logger.debug("[Haiku] >>> {}".format(haiku)) return haiku
def _post_proc(self, phrase_tree): """ 句生成完了後の処理. - 最後の3語を保持 - 生成した句の読みを保持 - 生成した句をリストとして保持 - 生成した句を保持 Args: 最後の PhraseTree インスタンス Returns: Phrase インスタンス """ assert phrase_tree is not None assert not PhraseTree.is_root(phrase_tree), "phrase_tree is not root" Phrase.text_list = PhraseTree.get_text_list(phrase_tree) Phrase.last_words = PhraseTree.get_last_words(phrase_tree) Phrase.last_vowel = PhraseTree.get_text_vowel(phrase_tree)
def test_construct_syllable_initialize_empty(self): """ 生成中,単語の候補リストが空担った場合 """ WordsData.words_data = self.EMPTY_LIST ChainsData.chains_data = self.EMPTY_DICT haiker = Haiker() root = PhraseTree.define_root( possible_next_words=list(ChainsData.chains_data.keys())) with self.assertRaises(ValueError): haiker.construct_syllable(root, self.TWELVE)
def test_get_text_list_first_and_last(self): """ 最初のツリー(root の次)に対して """ WordsData.words_data = self.SUCCESS_WORDS_TWELVE root = PhraseTree.define_root(possible_next_words=list(self.SUCCESS_CHAINS_TWELVE.keys())) word_tuple = ( Words( { "word": "ああああ", "vowel": "アアアア", "length": 4, "part": "名詞" } ), Words( { "word": "いいいい", "vowel": "イイイイ", "length": 4, "part": "名詞" } ), Words( { "word": "うううう", "vowel": "ウウウウ", "length": 4, "part": "名詞" } ) ) next_pt = PhraseTree(current_words=word_tuple, possible_next_words=list(self.SUCCESS_CHAINS_TWELVE.keys()), parent=root) root.next_tree = next_pt self.assertEqual( root.get_text_list(next_pt), ['ああああ', 'いいいい', 'うううう'] )
def _get_word(self, phrase_tree, seed=None, max_iterations=100): """ 単語リストからランダムに1つ取得. next_tree を取得的ない場合,None が代入される. """ next_tree = None for index in range(max_iterations): if not phrase_tree.possible_next_words: # possible_next_words が None, [] if PhraseTree.is_root(phrase_tree): raise ValueError( "Impossible to get word cause of Root Tree doesn't have any possible next words" ) return phrase_tree.parent, None else: if seed is None: random.shuffle(phrase_tree.possible_next_words) seed = phrase_tree.possible_next_words[ -1] # if 文外で remove するため pop ではない phrase_tree.possible_next_words.remove(seed) if seed in self._get_word_list() and \ ChainsData.chains_data[seed] != [None]: if ChainsData.chains_data[seed] == [None]: # この時点では,seed は文字列のタプルであり,Words クラスのタプルではない pass assert ChainsData.chains_data[seed] != [ None ], "ChainsData.chains_data: {}".format( ChainsData.chains_data) next_tree = PhraseTree( current_words=seed, possible_next_words=ChainsData.chains_data[seed], parent=phrase_tree) break seed = None assert phrase_tree is not None, "phrase_tree is None" return phrase_tree, next_tree
def test_post_proc(self): """ Phrase クラスが関連するテストは Phrase のメンバ変数を初期化してから行う. """ WordsData.words_data = self.SUCCESS_WORDS ChainsData.chains_data = self.SUCCESS_CHAINS haiker = Haiker() word_tuple = (Words({ "word": "古池", "vowel": "ウウイエ", "length": 4, "part": "名詞" }), Words({ "word": "蛙", "vowel": "アエウ", "length": 3, "part": "名詞" }), Words({ "word": "あ", "vowel": "ア", "length": 1, "part": "名詞" })) root = PhraseTree.define_root( possible_next_words=list(ChainsData.chains_data.keys())) second_tree = PhraseTree(current_words=word_tuple, parent=root) root.next_tree = second_tree # 中間処理 haiker._post_proc(second_tree) # Phrase 代入済み self.assertNotEqual(Phrase.text_list, list()) self.assertNotEqual(Phrase.last_words, tuple()) self.assertIsInstance(Phrase.last_vowel, str)
def test_construct_syllable_failure(self): WordsData.words_data = [{ "word": "あ", "vowel": "ア", "length": 1, "part": "名詞" }, { "word": "い", "vowel": "イ", "length": 1, "part": "名詞" }] ChainsData.chains_data = {"あ": ["い"]} haiker = Haiker() root = PhraseTree.define_root( possible_next_words=list(ChainsData.chains_data.keys())) with self.assertRaises(ValueError): haiker.construct_syllable(root, self.TWELVE)
def test_get_last_words(self): WordsData(self.WORDS) word_tuple = ( Words( { "word": "古池", "vowel": "ウウイエ", "length": 4, "part": "名詞" } ), Words( { "word": "蛙", "vowel": "アエウ", "length": 3, "part": "名詞" } ), Words( { "word": "あ", "vowel": "ア", "length": 1, "part": "名詞" } ) ) pt = PhraseTree(word_tuple) next_word_tuple = ( Words( { "word": "蛙", "vowel": "アエウ", "length": 3, "part": "名詞" } ), Words( { "word": "あ", "vowel": "ア", "length": 1, "part": "名詞" } ), Words( { "word": "い", "vowel": "イ", "length": 1, "part": "名詞" } ) ) next_pt = PhraseTree(next_word_tuple, parent=pt) pt.next_tree = next_pt self.assertEqual( PhraseTree.get_last_words(pt), next_word_tuple )
def test_count_phrase_len(self): WordsData(self.WORDS) word_tuple = ( Words( { "word": "古池", "vowel": "ウウイエ", "length": 4, "part": "名詞" } ), Words( { "word": "蛙", "vowel": "アエウ", "length": 3, "part": "名詞" } ), Words( { "word": "あ", "vowel": "ア", "length": 1, "part": "名詞" } ) ) root = PhraseTree.define_root(possible_next_words=list(self.SUCCESS_CHAINS.keys())) second_tree = PhraseTree(current_words=word_tuple, parent=root) root.next_tree = second_tree self.assertEqual( root.count_phrase_len(second_tree), 8 ) next_word_tuple = ( Words( { "word": "蛙", "vowel": "アエウ", "length": 3, "part": "名詞" } ), Words( { "word": "あ", "vowel": "ア", "length": 1, "part": "名詞" } ), Words( { "word": "いい", "vowel": "イイ", "length": 2, "part": "名詞" } ) ) third_tree = PhraseTree(next_word_tuple, parent=second_tree) self.assertEqual( PhraseTree.count_phrase_len(third_tree), 10 )
def test_get_text_list(self): WordsData(self.WORDS) word_tuple = ( Words( { "word": "古池", "vowel": "ウウイエ", "length": 4, "part": "名詞" } ), Words( { "word": "蛙", "vowel": "アエウ", "length": 3, "part": "名詞" } ), Words( { "word": "あ", "vowel": "ア", "length": 1, "part": "名詞" } ) ) root = PhraseTree.define_root(possible_next_words=list(self.SUCCESS_CHAINS.keys())) second_tree = PhraseTree(current_words=word_tuple, parent=root) root.next_tree = second_tree self.assertEqual( PhraseTree.get_text_list(second_tree), ['古池', '蛙', 'あ'] ) next_word_tuple = ( Words( { "word": "蛙", "vowel": "アエウ", "length": 3, "part": "名詞" } ), Words( { "word": "あ", "vowel": "ア", "length": 1, "part": "名詞" } ), Words( { "word": "いい", "vowel": "イイ", "length": 2, "part": "名詞" } ) ) third_tree = PhraseTree(current_words=next_word_tuple, possible_next_words=list(self.SUCCESS_CHAINS.keys()), parent=second_tree) second_tree.next_tree = third_tree self.assertEqual( PhraseTree.get_text_list(third_tree), ['古池', '蛙', 'あ', 'いい'] )