import spacy from spacy.tokens.token import Token from _io import TextIOWrapper from labelClasses import * from ctypes import * import sys ############################################################# #Input(文章題の入力) inn = int(input()) intxt='' for i in range(inn): intxt+=input() ############################################################# #GiNZA(文章題->木構造) #GiNZAの読み込みと解析 nlp = spacy.load('ja_ginza') doc = nlp(intxt) #解析結果の出力 for sent in doc.sents: for token in sent: print(token.i, token.orth_, token.lemma_, token.pos_, token.dep_, token.head.i,token.tag_) print('EOS') ###################################################### #(木構造->論理表現) #出力ファイルの名前 path_w = 'prolog.prolog' #数詞と数値の処理 def suusiTkn(tkn): for ctkn in tkn.children: if ctkn.pos_ == 'NUM': return ctkn.lemma_ return None #主語、目的語の処理 def objTkn(tkn): dIct = {'name':tkn.text,'type': 'n','syus':'_'} for ctkn in tkn.children: #付属語による主語・目的語の分類 for tg in caseTg: if ctkn.dep_ == tg: if 'は' == ctkn.lemma_ or 'が' == ctkn.lemma_: dIct['type'] = 'obj1' elif 'を' == ctkn.lemma_: dIct['type'] = 'obj2' elif 'より' == ctkn.lemma_: dIct['type'] = 'obj2' #修飾語の管理 for tg in syuushokuTg: if ctkn.dep_ == tg: dIct['syus']=ctkn.text return dIct #形容詞の処理 def adjTkn(tkn): dIct={'obj':{'type':'n'},'num':None} for ctkn in tkn.children: for tg in syuushokuTg: if ctkn.dep_ == tg and (dIct['obj']['type']=='n'): dIct['obj'] = objTkn(ctkn) for tg in suusiTg: if ctkn.dep_ == tg and dIct['num'] == None: dIct['num'] = suusiTkn(ctkn) return dIct #ルートのトークン def rooTkn(tkn): if not type(tkn) is Token: raise TypeError('not Token class') structDict={} if tkn.pos_ == 'VERB': structDict['verb'] = tkn.lemma_ elif tkn.pos_ == 'ADJ': structDict['adj'] = tkn.lemma_ rslt = adjTkn(tkn) if rslt['obj']['type'] != 'n': structDict[rslt['obj']['type']]=rslt['obj'] for ctkn in tkn.children: #print(ctkn.text) if ctkn.pos_ == 'NUM': structDict['num']=ctkn.lemma_ #structDict['num']={'num':ctkn.text,'suusi':tkn.text} if ctkn.pos_ == 'ADJ': structDict['adj'] = ctkn.lemma_ rslt = adjTkn(ctkn) if rslt['obj']['type'] != 'n': structDict[rslt['obj']['type']] = rslt['obj'] if rslt['num'] != None: structDict['num']=rslt['num'] for tg in objTg: if ctkn.dep_ == tg: rslt = objTkn(ctkn) structDict[rslt['type']]=rslt for tg in suusiTg: if ctkn.dep_ == tg: rslt = suusiTkn(ctkn) if rslt == None: continue structDict['num']=rslt return structDict #論理表現の構築 with open(path_w,mode='w') as f: #f.write('sem(') i=1 for sent in doc.sents: sd=rooTkn(sent.root) print(sd) f.write('sen(' + str(i) + ',') #形容詞 if sd.get('adj') == None: f.write('n,') else: f.write(sd['adj']+',') #述語 if sd.get('verb') == None: f.write('n,') else: f.write(sd['verb'] + ',') #主語 if sd.get('obj1') == None: f.write('object(_,_),') else: obj=sd['obj1'] f.write('object(' + obj['syus'] + ',' + obj['name'] + '),') #直接目的語 if sd.get('obj2') == None: f.write('object(_,_),') else: obj=sd['obj2'] f.write('object(' + obj['syus'] + ',' + obj['name'] + '),') #数値・数詞 if sd.get('num') == None: raise Exception('Sentence of No.'+str(i)+' does not exist number.') else: sd['num'] f.write(sd['num']) f.write(').\n') i+=1 ################################################################# #Prolog(論理表現->答え) #構築した動的ライブラリを呼び出す dll = cdll.LoadLibrary('AzProlog.dll') dll.Answer.argtypes = [c_char_p, c_int, POINTER(c_char_p), c_char_p] dll.Answer.restype=c_bool #各種パラメータ取得 op=['prolog'] opb = list(map(lambda x: x.encode('shift_jis'), op)) argcp = len(opb) argt = c_char_p * argcp argvp=argt(*opb) q='[\'prolog.prolog\'],[\'verb.prolog\'],[\'adv.prolog\'],[\'op.prolog\'],ans(A).'.encode('shift_jis') ans=(' '*256).encode('shift_jis') #構築した動的ライブラリを利用する #今回構築した関数↓ #第一引数:推論の入力(char*型) #第二引数:第三引数の文字列の長さ(int型) #第三引数:Prologのパラメータ(char**型) #第四引数:成功した場合推論結果を取得するパラメータ(空でないchar*型) #戻り値:推論が成功したか失敗したかを取得する(boolean型) rslt = dll.Answer(q, argcp, argvp, ans) ################################################################# #答え出力 print() print('-------------------------------------') print('Result:',end=' ') if rslt: print('success!') print() ansstr=ans.decode('shift_jis') print('Answer:',ansstr.split('\0')[0]) else: print('fail')